1 /* Demangler for GNU C++
2 Copyright 1989, 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.uucp)
4 Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
6 This file is part of the libiberty library.
7 Libiberty is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 Libiberty is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with libiberty; see the file COPYING.LIB. If
19 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
24 This file imports xmalloc and xrealloc, which are like malloc and
25 realloc except that they generate a fatal error if there is no
28 /* This file lives in both GCC and libiberty. When making changes, please
29 try not to break either. */
32 #include <sys/types.h>
41 #undef CURRENT_DEMANGLING_STYLE
42 #define CURRENT_DEMANGLING_STYLE work->options
44 extern char *xmalloc
PARAMS((unsigned));
45 extern char *xrealloc
PARAMS((char *, unsigned));
47 static const char *mystrstr
PARAMS ((const char *, const char *));
53 register const char *p
= s1
;
54 register int len
= strlen (s2
);
56 for (; (p
= strchr (p
, *s2
)) != 0; p
++)
58 if (strncmp (p
, s2
, len
) == 0)
66 /* In order to allow a single demangler executable to demangle strings
67 using various common values of CPLUS_MARKER, as well as any specific
68 one set at compile time, we maintain a string containing all the
69 commonly used ones, and check to see if the marker we are looking for
70 is in that string. CPLUS_MARKER is usually '$' on systems where the
71 assembler can deal with that. Where the assembler can't, it's usually
72 '.' (but on many systems '.' is used for other things). We put the
73 current defined CPLUS_MARKER first (which defaults to '$'), followed
74 by the next most common value, followed by an explicit '$' in case
75 the value of CPLUS_MARKER is not '$'.
77 We could avoid this if we could just get g++ to tell us what the actual
78 cplus marker character is as part of the debug information, perhaps by
79 ensuring that it is the character that terminates the gcc<n>_compiled
80 marker symbol (FIXME). */
82 #if !defined (CPLUS_MARKER)
83 #define CPLUS_MARKER '$'
86 enum demangling_styles current_demangling_style
= gnu_demangling
;
88 static char cplus_markers
[] = { CPLUS_MARKER
, '.', '$', '\0' };
91 set_cplus_marker_for_demangling (ch
)
94 cplus_markers
[0] = ch
;
97 /* Stuff that is shared between sub-routines.
98 Using a shared structure allows cplus_demangle to be reentrant. */
114 int static_type
; /* A static member function */
115 int const_type
; /* A const member function */
116 char **tmpl_argvec
; /* Template function arguments. */
117 int ntmpl_args
; /* The number of template function arguments. */
120 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
121 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
123 static const struct optable
129 {"nw", " new", DMGL_ANSI
}, /* new (1.92, ansi) */
130 {"dl", " delete", DMGL_ANSI
}, /* new (1.92, ansi) */
131 {"new", " new", 0}, /* old (1.91, and 1.x) */
132 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
133 {"vn", " new []", DMGL_ANSI
}, /* GNU, pending ansi */
134 {"vd", " delete []", DMGL_ANSI
}, /* GNU, pending ansi */
135 {"as", "=", DMGL_ANSI
}, /* ansi */
136 {"ne", "!=", DMGL_ANSI
}, /* old, ansi */
137 {"eq", "==", DMGL_ANSI
}, /* old, ansi */
138 {"ge", ">=", DMGL_ANSI
}, /* old, ansi */
139 {"gt", ">", DMGL_ANSI
}, /* old, ansi */
140 {"le", "<=", DMGL_ANSI
}, /* old, ansi */
141 {"lt", "<", DMGL_ANSI
}, /* old, ansi */
142 {"plus", "+", 0}, /* old */
143 {"pl", "+", DMGL_ANSI
}, /* ansi */
144 {"apl", "+=", DMGL_ANSI
}, /* ansi */
145 {"minus", "-", 0}, /* old */
146 {"mi", "-", DMGL_ANSI
}, /* ansi */
147 {"ami", "-=", DMGL_ANSI
}, /* ansi */
148 {"mult", "*", 0}, /* old */
149 {"ml", "*", DMGL_ANSI
}, /* ansi */
150 {"amu", "*=", DMGL_ANSI
}, /* ansi (ARM/Lucid) */
151 {"aml", "*=", DMGL_ANSI
}, /* ansi (GNU/g++) */
152 {"convert", "+", 0}, /* old (unary +) */
153 {"negate", "-", 0}, /* old (unary -) */
154 {"trunc_mod", "%", 0}, /* old */
155 {"md", "%", DMGL_ANSI
}, /* ansi */
156 {"amd", "%=", DMGL_ANSI
}, /* ansi */
157 {"trunc_div", "/", 0}, /* old */
158 {"dv", "/", DMGL_ANSI
}, /* ansi */
159 {"adv", "/=", DMGL_ANSI
}, /* ansi */
160 {"truth_andif", "&&", 0}, /* old */
161 {"aa", "&&", DMGL_ANSI
}, /* ansi */
162 {"truth_orif", "||", 0}, /* old */
163 {"oo", "||", DMGL_ANSI
}, /* ansi */
164 {"truth_not", "!", 0}, /* old */
165 {"nt", "!", DMGL_ANSI
}, /* ansi */
166 {"postincrement","++", 0}, /* old */
167 {"pp", "++", DMGL_ANSI
}, /* ansi */
168 {"postdecrement","--", 0}, /* old */
169 {"mm", "--", DMGL_ANSI
}, /* ansi */
170 {"bit_ior", "|", 0}, /* old */
171 {"or", "|", DMGL_ANSI
}, /* ansi */
172 {"aor", "|=", DMGL_ANSI
}, /* ansi */
173 {"bit_xor", "^", 0}, /* old */
174 {"er", "^", DMGL_ANSI
}, /* ansi */
175 {"aer", "^=", DMGL_ANSI
}, /* ansi */
176 {"bit_and", "&", 0}, /* old */
177 {"ad", "&", DMGL_ANSI
}, /* ansi */
178 {"aad", "&=", DMGL_ANSI
}, /* ansi */
179 {"bit_not", "~", 0}, /* old */
180 {"co", "~", DMGL_ANSI
}, /* ansi */
181 {"call", "()", 0}, /* old */
182 {"cl", "()", DMGL_ANSI
}, /* ansi */
183 {"alshift", "<<", 0}, /* old */
184 {"ls", "<<", DMGL_ANSI
}, /* ansi */
185 {"als", "<<=", DMGL_ANSI
}, /* ansi */
186 {"arshift", ">>", 0}, /* old */
187 {"rs", ">>", DMGL_ANSI
}, /* ansi */
188 {"ars", ">>=", DMGL_ANSI
}, /* ansi */
189 {"component", "->", 0}, /* old */
190 {"pt", "->", DMGL_ANSI
}, /* ansi; Lucid C++ form */
191 {"rf", "->", DMGL_ANSI
}, /* ansi; ARM/GNU form */
192 {"indirect", "*", 0}, /* old */
193 {"method_call", "->()", 0}, /* old */
194 {"addr", "&", 0}, /* old (unary &) */
195 {"array", "[]", 0}, /* old */
196 {"vc", "[]", DMGL_ANSI
}, /* ansi */
197 {"compound", ", ", 0}, /* old */
198 {"cm", ", ", DMGL_ANSI
}, /* ansi */
199 {"cond", "?:", 0}, /* old */
200 {"cn", "?:", DMGL_ANSI
}, /* pseudo-ansi */
201 {"max", ">?", 0}, /* old */
202 {"mx", ">?", DMGL_ANSI
}, /* pseudo-ansi */
203 {"min", "<?", 0}, /* old */
204 {"mn", "<?", DMGL_ANSI
}, /* pseudo-ansi */
205 {"nop", "", 0}, /* old (for operator=) */
206 {"rm", "->*", DMGL_ANSI
}, /* ansi */
207 {"sz", "sizeof ", DMGL_ANSI
} /* pseudo-ansi */
211 typedef struct string
/* Beware: these aren't required to be */
212 { /* '\0' terminated. */
213 char *b
; /* pointer to start of string */
214 char *p
; /* pointer after last character */
215 char *e
; /* pointer after end of allocated space */
218 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
219 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
220 string_prepend(str, " ");}
221 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
222 string_append(str, " ");}
223 #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
225 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
226 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
228 /* Prototypes for local functions */
231 mop_up
PARAMS ((struct work_stuff
*, string
*, int));
234 squangle_mop_up
PARAMS ((struct work_stuff
*));
238 demangle_method_args
PARAMS ((struct work_stuff
*, const char **, string
*));
242 internal_cplus_demangle
PARAMS ((struct work_stuff
*, const char *));
245 demangle_template_template_parm
PARAMS ((struct work_stuff
*work
,
246 const char **, string
*));
249 demangle_template
PARAMS ((struct work_stuff
*work
, const char **, string
*,
253 arm_pt
PARAMS ((struct work_stuff
*, const char *, int, const char **,
257 demangle_arm_pt
PARAMS ((struct work_stuff
*, const char **, int, string
*));
260 demangle_class_name
PARAMS ((struct work_stuff
*, const char **, string
*));
263 demangle_qualified
PARAMS ((struct work_stuff
*, const char **, string
*,
267 demangle_class
PARAMS ((struct work_stuff
*, const char **, string
*));
270 demangle_fund_type
PARAMS ((struct work_stuff
*, const char **, string
*));
273 demangle_signature
PARAMS ((struct work_stuff
*, const char **, string
*));
276 demangle_prefix
PARAMS ((struct work_stuff
*, const char **, string
*));
279 gnu_special
PARAMS ((struct work_stuff
*, const char **, string
*));
282 arm_special
PARAMS ((const char **, string
*));
285 string_need
PARAMS ((string
*, int));
288 string_delete
PARAMS ((string
*));
291 string_init
PARAMS ((string
*));
294 string_clear
PARAMS ((string
*));
298 string_empty
PARAMS ((string
*));
302 string_append
PARAMS ((string
*, const char *));
305 string_appends
PARAMS ((string
*, string
*));
308 string_appendn
PARAMS ((string
*, const char *, int));
311 string_prepend
PARAMS ((string
*, const char *));
314 string_prependn
PARAMS ((string
*, const char *, int));
317 get_count
PARAMS ((const char **, int *));
320 consume_count
PARAMS ((const char **));
323 consume_count_with_underscores
PARAMS ((const char**));
326 demangle_args
PARAMS ((struct work_stuff
*, const char **, string
*));
329 do_type
PARAMS ((struct work_stuff
*, const char **, string
*));
332 do_arg
PARAMS ((struct work_stuff
*, const char **, string
*));
335 demangle_function_name
PARAMS ((struct work_stuff
*, const char **, string
*,
339 remember_type
PARAMS ((struct work_stuff
*, const char *, int));
342 remember_Btype
PARAMS ((struct work_stuff
*, const char *, int, int));
345 register_Btype
PARAMS ((struct work_stuff
*));
348 remember_Ktype
PARAMS ((struct work_stuff
*, const char *, int));
351 forget_types
PARAMS ((struct work_stuff
*));
354 forget_B_and_K_types
PARAMS ((struct work_stuff
*));
357 string_prepends
PARAMS ((string
*, string
*));
360 demangle_template_value_parm
PARAMS ((struct work_stuff
*,
361 const char**, string
*));
363 /* Translate count to integer, consuming tokens in the process.
364 Conversion terminates on the first non-digit character.
365 Trying to consume something that isn't a count results in
366 no consumption of input and a return of 0. */
374 while (isdigit (**type
))
377 count
+= **type
- '0';
384 /* Like consume_count, but for counts that are preceded and followed
385 by '_' if they are greater than 10. Also, -1 is returned for
386 failure, since 0 can be a valid value. */
389 consume_count_with_underscores (mangled
)
390 const char **mangled
;
394 if (**mangled
== '_')
397 if (!isdigit (**mangled
))
400 idx
= consume_count (mangled
);
401 if (**mangled
!= '_')
402 /* The trailing underscore was missing. */
409 if (**mangled
< '0' || **mangled
> '9')
412 idx
= **mangled
- '0';
420 cplus_demangle_opname (opname
, result
, options
)
427 struct work_stuff work
[1];
430 len
= strlen(opname
);
433 memset ((char *) work
, 0, sizeof (work
));
434 work
->options
= options
;
436 if (opname
[0] == '_' && opname
[1] == '_'
437 && opname
[2] == 'o' && opname
[3] == 'p')
440 /* type conversion operator. */
442 if (do_type (work
, &tem
, &type
))
444 strcat (result
, "operator ");
445 strncat (result
, type
.b
, type
.p
- type
.b
);
446 string_delete (&type
);
450 else if (opname
[0] == '_' && opname
[1] == '_'
451 && opname
[2] >= 'a' && opname
[2] <= 'z'
452 && opname
[3] >= 'a' && opname
[3] <= 'z')
454 if (opname
[4] == '\0')
458 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
460 if (strlen (optable
[i
].in
) == 2
461 && memcmp (optable
[i
].in
, opname
+ 2, 2) == 0)
463 strcat (result
, "operator");
464 strcat (result
, optable
[i
].out
);
472 if (opname
[2] == 'a' && opname
[5] == '\0')
476 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
478 if (strlen (optable
[i
].in
) == 3
479 && memcmp (optable
[i
].in
, opname
+ 2, 3) == 0)
481 strcat (result
, "operator");
482 strcat (result
, optable
[i
].out
);
493 && strchr (cplus_markers
, opname
[2]) != NULL
)
495 /* see if it's an assignment expression */
496 if (len
>= 10 /* op$assign_ */
497 && memcmp (opname
+ 3, "assign_", 7) == 0)
500 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
503 if (strlen (optable
[i
].in
) == len1
504 && memcmp (optable
[i
].in
, opname
+ 10, len1
) == 0)
506 strcat (result
, "operator");
507 strcat (result
, optable
[i
].out
);
508 strcat (result
, "=");
517 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
520 if (strlen (optable
[i
].in
) == len1
521 && memcmp (optable
[i
].in
, opname
+ 3, len1
) == 0)
523 strcat (result
, "operator");
524 strcat (result
, optable
[i
].out
);
531 else if (len
>= 5 && memcmp (opname
, "type", 4) == 0
532 && strchr (cplus_markers
, opname
[4]) != NULL
)
534 /* type conversion operator */
536 if (do_type (work
, &tem
, &type
))
538 strcat (result
, "operator ");
539 strncat (result
, type
.b
, type
.p
- type
.b
);
540 string_delete (&type
);
544 squangle_mop_up (work
);
548 /* Takes operator name as e.g. "++" and returns mangled
549 operator name (e.g. "postincrement_expr"), or NULL if not found.
551 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
552 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
555 cplus_mangle_opname (opname
, options
)
562 len
= strlen (opname
);
563 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
565 if (strlen (optable
[i
].out
) == len
566 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
567 && memcmp (optable
[i
].out
, opname
, len
) == 0)
568 return optable
[i
].in
;
573 /* char *cplus_demangle (const char *mangled, int options)
575 If MANGLED is a mangled function name produced by GNU C++, then
576 a pointer to a malloced string giving a C++ representation
577 of the name will be returned; otherwise NULL will be returned.
578 It is the caller's responsibility to free the string which
581 The OPTIONS arg may contain one or more of the following bits:
583 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
585 DMGL_PARAMS Function parameters are included.
589 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
590 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
591 cplus_demangle ("foo__1Ai", 0) => "A::foo"
593 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
594 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
595 cplus_demangle ("foo__1Afe", 0) => "A::foo"
597 Note that any leading underscores, or other such characters prepended by
598 the compilation system, are presumed to have already been stripped from
602 cplus_demangle (mangled
, options
)
607 struct work_stuff work
[1];
608 memset ((char *) work
, 0, sizeof (work
));
609 work
-> options
= options
;
610 if ((work
-> options
& DMGL_STYLE_MASK
) == 0)
611 work
-> options
|= (int) current_demangling_style
& DMGL_STYLE_MASK
;
613 ret
= internal_cplus_demangle (work
, mangled
);
614 squangle_mop_up (work
);
619 /* This function performs most of what cplus_demangle use to do, but
620 to be able to demangle a name with a B, K or n code, we need to
621 have a longer term memory of what types have been seen. The original
622 now intializes and cleans up the squangle code info, while internal
623 calls go directly to this routine to avoid resetting that info. */
626 internal_cplus_demangle (work
, mangled
)
627 struct work_stuff
*work
;
633 char *demangled
= NULL
;
635 s1
= work
->constructor
;
636 s2
= work
->destructor
;
637 s3
= work
->static_type
;
638 s4
= work
->const_type
;
639 work
->constructor
= work
->destructor
= 0;
640 work
->static_type
= work
->const_type
= 0;
642 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
646 /* First check to see if gnu style demangling is active and if the
647 string to be demangled contains a CPLUS_MARKER. If so, attempt to
648 recognize one of the gnu special forms rather than looking for a
649 standard prefix. In particular, don't worry about whether there
650 is a "__" string in the mangled string. Consider "_$_5__foo" for
653 if ((AUTO_DEMANGLING
|| GNU_DEMANGLING
))
655 success
= gnu_special (work
, &mangled
, &decl
);
659 success
= demangle_prefix (work
, &mangled
, &decl
);
661 if (success
&& (*mangled
!= '\0'))
663 success
= demangle_signature (work
, &mangled
, &decl
);
665 if (work
->constructor
== 2)
667 string_prepend (&decl
, "global constructors keyed to ");
668 work
->constructor
= 0;
670 else if (work
->destructor
== 2)
672 string_prepend (&decl
, "global destructors keyed to ");
673 work
->destructor
= 0;
675 demangled
= mop_up (work
, &decl
, success
);
677 work
->constructor
= s1
;
678 work
->destructor
= s2
;
679 work
->static_type
= s3
;
680 work
->const_type
= s4
;
685 /* Clear out and squangling related storage */
687 squangle_mop_up (work
)
688 struct work_stuff
*work
;
690 /* clean up the B and K type mangling types. */
691 forget_B_and_K_types (work
);
692 if (work
-> btypevec
!= NULL
)
694 free ((char *) work
-> btypevec
);
696 if (work
-> ktypevec
!= NULL
)
698 free ((char *) work
-> ktypevec
);
702 /* Clear out any mangled storage */
705 mop_up (work
, declp
, success
)
706 struct work_stuff
*work
;
710 char *demangled
= NULL
;
712 /* Discard the remembered types, if any. */
715 if (work
-> typevec
!= NULL
)
717 free ((char *) work
-> typevec
);
718 work
-> typevec
= NULL
;
720 if (work
->tmpl_argvec
)
724 for (i
= 0; i
< work
->ntmpl_args
; i
++)
725 if (work
->tmpl_argvec
[i
])
726 free ((char*) work
->tmpl_argvec
[i
]);
728 free ((char*) work
->tmpl_argvec
);
729 work
->tmpl_argvec
= NULL
;
732 /* If demangling was successful, ensure that the demangled string is null
733 terminated and return it. Otherwise, free the demangling decl. */
737 string_delete (declp
);
741 string_appendn (declp
, "", 1);
742 demangled
= declp
-> b
;
751 demangle_signature -- demangle the signature part of a mangled name
756 demangle_signature (struct work_stuff *work, const char **mangled,
761 Consume and demangle the signature portion of the mangled name.
763 DECLP is the string where demangled output is being built. At
764 entry it contains the demangled root name from the mangled name
765 prefix. I.E. either a demangled operator name or the root function
766 name. In some special cases, it may contain nothing.
768 *MANGLED points to the current unconsumed location in the mangled
769 name. As tokens are consumed and demangling is performed, the
770 pointer is updated to continuously point at the next token to
773 Demangling GNU style mangled names is nasty because there is no
774 explicit token that marks the start of the outermost function
778 demangle_signature (work
, mangled
, declp
)
779 struct work_stuff
*work
;
780 const char **mangled
;
786 int expect_return_type
= 0;
787 const char *oldmangled
= NULL
;
791 while (success
&& (**mangled
!= '\0'))
796 oldmangled
= *mangled
;
797 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
800 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
802 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
810 oldmangled
= *mangled
;
811 success
= demangle_qualified (work
, mangled
, declp
, 1, 0);
812 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
820 /* Static member function */
821 if (oldmangled
== NULL
)
823 oldmangled
= *mangled
;
826 work
-> static_type
= 1;
830 /* a const member function */
831 if (oldmangled
== NULL
)
833 oldmangled
= *mangled
;
836 work
-> const_type
= 1;
839 case '0': case '1': case '2': case '3': case '4':
840 case '5': case '6': case '7': case '8': case '9':
841 if (oldmangled
== NULL
)
843 oldmangled
= *mangled
;
845 success
= demangle_class (work
, mangled
, declp
);
848 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
850 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
859 /* ARM style demangling includes a specific 'F' character after
860 the class name. For GNU style, it is just implied. So we can
861 safely just consume any 'F' at this point and be compatible
862 with either style. */
868 /* For lucid/ARM style we have to forget any types we might
869 have remembered up to this point, since they were not argument
870 types. GNU style considers all types seen as available for
871 back references. See comment in demangle_args() */
873 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
877 success
= demangle_args (work
, mangled
, declp
);
882 string_init(&trawname
);
884 if (oldmangled
== NULL
)
886 oldmangled
= *mangled
;
888 success
= demangle_template (work
, mangled
, &tname
, &trawname
, 1);
891 remember_type (work
, oldmangled
, *mangled
- oldmangled
);
893 string_append (&tname
, "::");
895 string_prepends(declp
, &tname
);
896 if (work
-> destructor
& 1)
898 string_prepend (&trawname
, "~");
899 string_appends (declp
, &trawname
);
900 work
->destructor
-= 1;
902 if ((work
->constructor
& 1) || (work
->destructor
& 1))
904 string_appends (declp
, &trawname
);
905 work
->constructor
-= 1;
907 string_delete(&trawname
);
908 string_delete(&tname
);
914 if (GNU_DEMANGLING
&& expect_return_type
)
916 /* Read the return type. */
918 string_init (&return_type
);
921 success
= do_type (work
, mangled
, &return_type
);
922 APPEND_BLANK (&return_type
);
924 string_prepends (declp
, &return_type
);
925 string_delete (&return_type
);
929 /* At the outermost level, we cannot have a return type specified,
930 so if we run into another '_' at this point we are dealing with
931 a mangled name that is either bogus, or has been mangled by
932 some algorithm we don't know how to deal with. So just
933 reject the entire demangling. */
940 /* A G++ template function. Read the template arguments. */
941 success
= demangle_template (work
, mangled
, declp
, 0, 0);
942 if (!(work
->constructor
& 1))
943 expect_return_type
= 1;
952 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
954 /* Assume we have stumbled onto the first outermost function
955 argument token, and start processing args. */
957 success
= demangle_args (work
, mangled
, declp
);
961 /* Non-GNU demanglers use a specific token to mark the start
962 of the outermost function argument tokens. Typically 'F',
963 for ARM-demangling, for example. So if we find something
964 we are not prepared for, it must be an error. */
970 if (AUTO_DEMANGLING || GNU_DEMANGLING)
973 if (success
&& expect_func
)
976 success
= demangle_args (work
, mangled
, declp
);
977 /* Since template include the mangling of their return types,
978 we must set expect_func to 0 so that we don't try do
979 demangle more arguments the next time we get here. */
984 if (success
&& !func_done
)
986 if (AUTO_DEMANGLING
|| GNU_DEMANGLING
)
988 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
989 bar__3fooi is 'foo::bar(int)'. We get here when we find the
990 first case, and need to ensure that the '(void)' gets added to
991 the current declp. Note that with ARM, the first case
992 represents the name of a static data member 'foo::bar',
993 which is in the current declp, so we leave it alone. */
994 success
= demangle_args (work
, mangled
, declp
);
997 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
999 string_append (declp
, " static");
1001 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
1003 string_append (declp
, " const");
1011 demangle_method_args (work
, mangled
, declp
)
1012 struct work_stuff
*work
;
1013 const char **mangled
;
1018 if (work
-> static_type
)
1020 string_append (declp
, *mangled
+ 1);
1021 *mangled
+= strlen (*mangled
);
1026 success
= demangle_args (work
, mangled
, declp
);
1034 demangle_template_template_parm (work
, mangled
, tname
)
1035 struct work_stuff
*work
;
1036 const char **mangled
;
1045 string_append (tname
, "template <");
1046 /* get size of template parameter list */
1047 if (get_count (mangled
, &r
))
1049 for (i
= 0; i
< r
; i
++)
1053 string_append (tname
, ", ");
1056 /* Z for type parameters */
1057 if (**mangled
== 'Z')
1060 string_append (tname
, "class");
1062 /* z for template parameters */
1063 else if (**mangled
== 'z')
1067 demangle_template_template_parm (work
, mangled
, tname
);
1075 /* temp is initialized in do_type */
1076 success
= do_type (work
, mangled
, &temp
);
1079 string_appends (tname
, &temp
);
1081 string_delete(&temp
);
1091 if (tname
->p
[-1] == '>')
1092 string_append (tname
, " ");
1093 string_append (tname
, "> class");
1098 demangle_integral_value (work
, mangled
, s
)
1099 struct work_stuff
*work
;
1100 const char** mangled
;
1105 if (**mangled
== 'E')
1107 int need_operator
= 0;
1110 string_appendn (s
, "(", 1);
1112 while (success
&& **mangled
!= 'W' && **mangled
!= '\0')
1121 len
= strlen (*mangled
);
1124 i
< sizeof (optable
) / sizeof (optable
[0]);
1127 size_t l
= strlen (optable
[i
].in
);
1130 && memcmp (optable
[i
].in
, *mangled
, l
) == 0)
1132 string_appendn (s
, " ", 1);
1133 string_append (s
, optable
[i
].out
);
1134 string_appendn (s
, " ", 1);
1147 success
= demangle_template_value_parm (work
, mangled
, s
);
1150 if (**mangled
!= 'W')
1154 string_appendn (s
, ")", 1);
1158 else if (**mangled
== 'Q' || **mangled
== 'K')
1159 success
= demangle_qualified (work
, mangled
, s
, 0, 1);
1164 if (**mangled
== 'm')
1166 string_appendn (s
, "-", 1);
1169 while (isdigit (**mangled
))
1171 string_appendn (s
, *mangled
, 1);
1181 demangle_template_value_parm (work
, mangled
, s
)
1182 struct work_stuff
*work
;
1183 const char **mangled
;
1186 const char *old_p
= *mangled
;
1189 int is_integral
= 0;
1195 while (*old_p
&& !done
)
1202 done
= is_pointer
= 1;
1204 case 'C': /* const */
1205 case 'S': /* explicitly signed [char] */
1206 case 'U': /* unsigned */
1207 case 'V': /* volatile */
1208 case 'F': /* function */
1209 case 'M': /* member function */
1211 case 'J': /* complex */
1214 case 'E': /* expression */
1215 case 'Q': /* qualified name */
1216 case 'K': /* qualified name */
1217 done
= is_integral
= 1;
1219 case 'B': /* squangled name */
1220 done
= is_integral
= 1;
1222 case 'T': /* remembered type */
1225 case 'v': /* void */
1228 case 'x': /* long long */
1229 case 'l': /* long */
1231 case 's': /* short */
1232 case 'w': /* wchar_t */
1233 done
= is_integral
= 1;
1235 case 'b': /* bool */
1238 case 'c': /* char */
1241 case 'r': /* long double */
1242 case 'd': /* double */
1243 case 'f': /* float */
1247 /* it's probably user defined type, let's assume
1248 it's integral, it seems hard to figure out
1249 what it really is */
1250 done
= is_integral
= 1;
1253 if (**mangled
== 'Y')
1255 /* The next argument is a template parameter. */
1259 idx
= consume_count_with_underscores (mangled
);
1261 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1262 || consume_count_with_underscores (mangled
) == -1)
1264 if (work
->tmpl_argvec
)
1265 string_append (s
, work
->tmpl_argvec
[idx
]);
1269 sprintf(buf
, "T%d", idx
);
1270 string_append (s
, buf
);
1273 else if (is_integral
)
1274 success
= demangle_integral_value (work
, mangled
, s
);
1279 if (**mangled
== 'm')
1281 string_appendn (s
, "-", 1);
1284 string_appendn (s
, "'", 1);
1285 val
= consume_count(mangled
);
1290 string_appendn (s
, &tmp
[0], 1);
1291 string_appendn (s
, "'", 1);
1295 int val
= consume_count (mangled
);
1297 string_appendn (s
, "false", 5);
1299 string_appendn (s
, "true", 4);
1305 if (**mangled
== 'm')
1307 string_appendn (s
, "-", 1);
1310 while (isdigit (**mangled
))
1312 string_appendn (s
, *mangled
, 1);
1315 if (**mangled
== '.') /* fraction */
1317 string_appendn (s
, ".", 1);
1319 while (isdigit (**mangled
))
1321 string_appendn (s
, *mangled
, 1);
1325 if (**mangled
== 'e') /* exponent */
1327 string_appendn (s
, "e", 1);
1329 while (isdigit (**mangled
))
1331 string_appendn (s
, *mangled
, 1);
1336 else if (is_pointer
)
1338 int symbol_len
= consume_count (mangled
);
1339 if (symbol_len
== 0)
1341 if (symbol_len
== 0)
1342 string_appendn (s
, "0", 1);
1345 char *p
= xmalloc (symbol_len
+ 1), *q
;
1346 strncpy (p
, *mangled
, symbol_len
);
1347 p
[symbol_len
] = '\0';
1348 q
= internal_cplus_demangle (work
, p
);
1349 string_appendn (s
, "&", 1);
1352 string_append (s
, q
);
1356 string_append (s
, p
);
1359 *mangled
+= symbol_len
;
1366 demangle_template (work
, mangled
, tname
, trawname
, is_type
)
1367 struct work_stuff
*work
;
1368 const char **mangled
;
1384 /* get template name */
1385 if (**mangled
== 'z')
1391 idx
= consume_count_with_underscores (mangled
);
1393 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
1394 || consume_count_with_underscores (mangled
) == -1)
1398 if (work
->tmpl_argvec
)
1400 string_append (tname
, work
->tmpl_argvec
[idx
]);
1402 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1407 sprintf(buf
, "T%d", idx
);
1408 string_append (tname
, buf
);
1410 string_append (trawname
, work
->tmpl_argvec
[idx
]);
1415 if ((r
= consume_count (mangled
)) == 0 || strlen (*mangled
) < r
)
1420 string_appendn (trawname
, *mangled
, r
);
1421 string_appendn (tname
, *mangled
, r
);
1425 string_append (tname
, "<");
1426 /* get size of template parameter list */
1427 if (!get_count (mangled
, &r
))
1433 /* Create an array for saving the template argument values. */
1434 work
->tmpl_argvec
= (char**) xmalloc (r
* sizeof (char *));
1435 work
->ntmpl_args
= r
;
1436 for (i
= 0; i
< r
; i
++)
1437 work
->tmpl_argvec
[i
] = 0;
1439 for (i
= 0; i
< r
; i
++)
1443 string_append (tname
, ", ");
1445 /* Z for type parameters */
1446 if (**mangled
== 'Z')
1449 /* temp is initialized in do_type */
1450 success
= do_type (work
, mangled
, &temp
);
1453 string_appends (tname
, &temp
);
1457 /* Save the template argument. */
1458 int len
= temp
.p
- temp
.b
;
1459 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1460 memcpy (work
->tmpl_argvec
[i
], temp
.b
, len
);
1461 work
->tmpl_argvec
[i
][len
] = '\0';
1464 string_delete(&temp
);
1470 /* z for template parameters */
1471 else if (**mangled
== 'z')
1475 success
= demangle_template_template_parm (work
, mangled
, tname
);
1478 && (r2
= consume_count (mangled
)) > 0 && strlen (*mangled
) >= r2
)
1480 string_append (tname
, " ");
1481 string_appendn (tname
, *mangled
, r2
);
1484 /* Save the template argument. */
1486 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1487 memcpy (work
->tmpl_argvec
[i
], *mangled
, len
);
1488 work
->tmpl_argvec
[i
][len
] = '\0';
1502 /* otherwise, value parameter */
1504 /* temp is initialized in do_type */
1505 success
= do_type (work
, mangled
, &temp
);
1509 string_appends (s, &temp);
1512 string_delete(&temp
);
1518 string_append (s, "=");
1529 success
= demangle_template_value_parm (work
, mangled
, s
);
1541 int len
= s
->p
- s
->b
;
1542 work
->tmpl_argvec
[i
] = xmalloc (len
+ 1);
1543 memcpy (work
->tmpl_argvec
[i
], s
->b
, len
);
1544 work
->tmpl_argvec
[i
][len
] = '\0';
1546 string_appends (tname
, s
);
1553 if (tname
->p
[-1] == '>')
1554 string_append (tname
, " ");
1555 string_append (tname
, ">");
1559 if (work -> static_type)
1561 string_append (declp, *mangled + 1);
1562 *mangled += strlen (*mangled);
1567 success = demangle_args (work, mangled, declp);
1575 arm_pt (work
, mangled
, n
, anchor
, args
)
1576 struct work_stuff
*work
;
1577 const char *mangled
;
1579 const char **anchor
, **args
;
1582 if (ARM_DEMANGLING
&& (*anchor
= mystrstr (mangled
, "__pt__")))
1585 *args
= *anchor
+ 6;
1586 len
= consume_count (args
);
1587 if (*args
+ len
== mangled
+ n
&& **args
== '_')
1597 demangle_arm_pt (work
, mangled
, n
, declp
)
1598 struct work_stuff
*work
;
1599 const char **mangled
;
1605 const char *e
= *mangled
+ n
;
1608 if (arm_pt (work
, *mangled
, n
, &p
, &args
))
1612 string_appendn (declp
, *mangled
, p
- *mangled
);
1613 string_append (declp
, "<");
1614 /* should do error checking here */
1616 string_clear (&arg
);
1617 do_type (work
, &args
, &arg
);
1618 string_appends (declp
, &arg
);
1619 string_append (declp
, ",");
1621 string_delete (&arg
);
1623 string_append (declp
, ">");
1627 string_appendn (declp
, *mangled
, n
);
1633 demangle_class_name (work
, mangled
, declp
)
1634 struct work_stuff
*work
;
1635 const char **mangled
;
1641 n
= consume_count (mangled
);
1642 if (strlen (*mangled
) >= n
)
1644 demangle_arm_pt (work
, mangled
, n
, declp
);
1655 demangle_class -- demangle a mangled class sequence
1660 demangle_class (struct work_stuff *work, const char **mangled,
1665 DECLP points to the buffer into which demangling is being done.
1667 *MANGLED points to the current token to be demangled. On input,
1668 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1669 On exit, it points to the next token after the mangled class on
1670 success, or the first unconsumed token on failure.
1672 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1673 we are demangling a constructor or destructor. In this case
1674 we prepend "class::class" or "class::~class" to DECLP.
1676 Otherwise, we prepend "class::" to the current DECLP.
1678 Reset the constructor/destructor flags once they have been
1679 "consumed". This allows demangle_class to be called later during
1680 the same demangling, to do normal class demangling.
1682 Returns 1 if demangling is successful, 0 otherwise.
1687 demangle_class (work
, mangled
, declp
)
1688 struct work_stuff
*work
;
1689 const char **mangled
;
1696 string_init (&class_name
);
1697 btype
= register_Btype (work
);
1698 if (demangle_class_name (work
, mangled
, &class_name
))
1700 if ((work
->constructor
& 1) || (work
->destructor
& 1))
1702 string_prepends (declp
, &class_name
);
1703 if (work
-> destructor
& 1)
1705 string_prepend (declp
, "~");
1706 work
-> destructor
-= 1;
1710 work
-> constructor
-= 1;
1713 remember_Ktype (work
, class_name
.b
, LEN_STRING(&class_name
));
1714 remember_Btype (work
, class_name
.b
, LEN_STRING(&class_name
), btype
);
1715 string_prepend (declp
, "::");
1716 string_prepends (declp
, &class_name
);
1719 string_delete (&class_name
);
1727 demangle_prefix -- consume the mangled name prefix and find signature
1732 demangle_prefix (struct work_stuff *work, const char **mangled,
1737 Consume and demangle the prefix of the mangled name.
1739 DECLP points to the string buffer into which demangled output is
1740 placed. On entry, the buffer is empty. On exit it contains
1741 the root function name, the demangled operator name, or in some
1742 special cases either nothing or the completely demangled result.
1744 MANGLED points to the current pointer into the mangled name. As each
1745 token of the mangled name is consumed, it is updated. Upon entry
1746 the current mangled name pointer points to the first character of
1747 the mangled name. Upon exit, it should point to the first character
1748 of the signature if demangling was successful, or to the first
1749 unconsumed character if demangling of the prefix was unsuccessful.
1751 Returns 1 on success, 0 otherwise.
1755 demangle_prefix (work
, mangled
, declp
)
1756 struct work_stuff
*work
;
1757 const char **mangled
;
1764 if (strlen(*mangled
) >= 11 && strncmp(*mangled
, "_GLOBAL_", 8) == 0)
1766 char *marker
= strchr (cplus_markers
, (*mangled
)[8]);
1767 if (marker
!= NULL
&& *marker
== (*mangled
)[10])
1769 if ((*mangled
)[9] == 'D')
1771 /* it's a GNU global destructor to be executed at program exit */
1773 work
->destructor
= 2;
1774 if (gnu_special (work
, mangled
, declp
))
1777 else if ((*mangled
)[9] == 'I')
1779 /* it's a GNU global constructor to be executed at program init */
1781 work
->constructor
= 2;
1782 if (gnu_special (work
, mangled
, declp
))
1787 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__std__", 7) == 0)
1789 /* it's a ARM global destructor to be executed at program exit */
1791 work
->destructor
= 2;
1793 else if (ARM_DEMANGLING
&& strncmp(*mangled
, "__sti__", 7) == 0)
1795 /* it's a ARM global constructor to be executed at program initial */
1797 work
->constructor
= 2;
1800 /* This block of code is a reduction in strength time optimization
1802 scan = mystrstr (*mangled, "__"); */
1808 scan
= strchr (scan
, '_');
1809 } while (scan
!= NULL
&& *++scan
!= '_');
1811 if (scan
!= NULL
) --scan
;
1816 /* We found a sequence of two or more '_', ensure that we start at
1817 the last pair in the sequence. */
1818 i
= strspn (scan
, "_");
1829 else if (work
-> static_type
)
1831 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
1836 else if ((scan
== *mangled
)
1837 && (isdigit (scan
[2]) || (scan
[2] == 'Q') || (scan
[2] == 't')
1838 || (scan
[2] == 'K') || (scan
[2] == 'H')))
1840 /* The ARM says nothing about the mangling of local variables.
1841 But cfront mangles local variables by prepending __<nesting_level>
1842 to them. As an extension to ARM demangling we handle this case. */
1843 if ((LUCID_DEMANGLING
|| ARM_DEMANGLING
) && isdigit (scan
[2]))
1845 *mangled
= scan
+ 2;
1846 consume_count (mangled
);
1847 string_append (declp
, *mangled
);
1848 *mangled
+= strlen (*mangled
);
1853 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1854 names like __Q2_3foo3bar for nested type names. So don't accept
1855 this style of constructor for cfront demangling. A GNU
1856 style member-template constructor starts with 'H'. */
1857 if (!(LUCID_DEMANGLING
|| ARM_DEMANGLING
))
1858 work
-> constructor
+= 1;
1859 *mangled
= scan
+ 2;
1862 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
1864 /* Mangled name starts with "__". Skip over any leading '_' characters,
1865 then find the next "__" that separates the prefix from the signature.
1867 if (!(ARM_DEMANGLING
|| LUCID_DEMANGLING
)
1868 || (arm_special (mangled
, declp
) == 0))
1870 while (*scan
== '_')
1874 if ((scan
= mystrstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
1876 /* No separator (I.E. "__not_mangled"), or empty signature
1877 (I.E. "__not_mangled_either__") */
1882 demangle_function_name (work
, mangled
, declp
, scan
);
1886 else if (ARM_DEMANGLING
&& scan
[2] == 'p' && scan
[3] == 't')
1888 /* Cfront-style parameterized type. Handled later as a signature. */
1892 demangle_arm_pt (work
, mangled
, strlen (*mangled
), declp
);
1894 else if (*(scan
+ 2) != '\0')
1896 /* Mangled name does not start with "__" but does have one somewhere
1897 in there with non empty stuff after it. Looks like a global
1899 demangle_function_name (work
, mangled
, declp
, scan
);
1903 /* Doesn't look like a mangled name */
1907 if (!success
&& (work
->constructor
== 2 || work
->destructor
== 2))
1909 string_append (declp
, *mangled
);
1910 *mangled
+= strlen (*mangled
);
1920 gnu_special -- special handling of gnu mangled strings
1925 gnu_special (struct work_stuff *work, const char **mangled,
1931 Process some special GNU style mangling forms that don't fit
1932 the normal pattern. For example:
1934 _$_3foo (destructor for class foo)
1935 _vt$foo (foo virtual table)
1936 _vt$foo$bar (foo::bar virtual table)
1937 __vt_foo (foo virtual table, new style with thunks)
1938 _3foo$varname (static data member)
1939 _Q22rs2tu$vw (static data member)
1940 __t6vector1Zii (constructor with template)
1941 __thunk_4__$_7ostream (virtual function thunk)
1945 gnu_special (work
, mangled
, declp
)
1946 struct work_stuff
*work
;
1947 const char **mangled
;
1954 if ((*mangled
)[0] == '_'
1955 && strchr (cplus_markers
, (*mangled
)[1]) != NULL
1956 && (*mangled
)[2] == '_')
1958 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1960 work
-> destructor
+= 1;
1962 else if ((*mangled
)[0] == '_'
1963 && (((*mangled
)[1] == '_'
1964 && (*mangled
)[2] == 'v'
1965 && (*mangled
)[3] == 't'
1966 && (*mangled
)[4] == '_')
1967 || ((*mangled
)[1] == 'v'
1968 && (*mangled
)[2] == 't'
1969 && strchr (cplus_markers
, (*mangled
)[3]) != NULL
)))
1971 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1972 and create the decl. Note that we consume the entire mangled
1973 input string, which means that demangle_signature has no work
1975 if ((*mangled
)[2] == 'v')
1976 (*mangled
) += 5; /* New style, with thunks: "__vt_" */
1978 (*mangled
) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1979 while (**mangled
!= '\0')
1981 p
= strpbrk (*mangled
, cplus_markers
);
1986 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
1989 success
= demangle_template (work
, mangled
, declp
, 0, 1);
1992 if (isdigit(*mangled
[0]))
1994 n
= consume_count(mangled
);
1995 /* We may be seeing a too-large size, or else a
1996 ".<digits>" indicating a static local symbol. In
1997 any case, declare victory and move on; *don't* try
1998 to use n to allocate. */
1999 if (n
> strlen (*mangled
))
2007 n
= strcspn (*mangled
, cplus_markers
);
2009 string_appendn (declp
, *mangled
, n
);
2013 if (success
&& ((p
== NULL
) || (p
== *mangled
)))
2017 string_append (declp
, "::");
2028 string_append (declp
, " virtual table");
2030 else if ((*mangled
)[0] == '_'
2031 && (strchr("0123456789Qt", (*mangled
)[1]) != NULL
)
2032 && (p
= strpbrk (*mangled
, cplus_markers
)) != NULL
)
2034 /* static data member, "_3foo$varname" for example */
2040 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2043 success
= demangle_template (work
, mangled
, declp
, 0, 1);
2046 n
= consume_count (mangled
);
2047 string_appendn (declp
, *mangled
, n
);
2050 if (success
&& (p
== *mangled
))
2052 /* Consumed everything up to the cplus_marker, append the
2055 string_append (declp
, "::");
2056 n
= strlen (*mangled
);
2057 string_appendn (declp
, *mangled
, n
);
2065 else if (strncmp (*mangled
, "__thunk_", 8) == 0)
2067 int delta
= ((*mangled
) += 8, consume_count (mangled
));
2068 char *method
= internal_cplus_demangle (work
, ++*mangled
);
2072 sprintf (buf
, "virtual function thunk (delta:%d) for ", -delta
);
2073 string_append (declp
, buf
);
2074 string_append (declp
, method
);
2076 n
= strlen (*mangled
);
2084 else if (strncmp (*mangled
, "__t", 3) == 0
2085 && ((*mangled
)[3] == 'i' || (*mangled
)[3] == 'f'))
2087 p
= (*mangled
)[3] == 'i' ? " type_info node" : " type_info function";
2093 success
= demangle_qualified (work
, mangled
, declp
, 0, 1);
2096 success
= demangle_template (work
, mangled
, declp
, 0, 1);
2099 success
= demangle_fund_type (work
, mangled
, declp
);
2102 if (success
&& **mangled
!= '\0')
2105 string_append (declp
, p
);
2118 arm_special -- special handling of ARM/lucid mangled strings
2123 arm_special (const char **mangled,
2129 Process some special ARM style mangling forms that don't fit
2130 the normal pattern. For example:
2132 __vtbl__3foo (foo virtual table)
2133 __vtbl__3foo__3bar (bar::foo virtual table)
2138 arm_special (mangled
, declp
)
2139 const char **mangled
;
2146 if (strncmp (*mangled
, ARM_VTABLE_STRING
, ARM_VTABLE_STRLEN
) == 0)
2148 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2149 and create the decl. Note that we consume the entire mangled
2150 input string, which means that demangle_signature has no work
2152 scan
= *mangled
+ ARM_VTABLE_STRLEN
;
2153 while (*scan
!= '\0') /* first check it can be demangled */
2155 n
= consume_count (&scan
);
2158 return (0); /* no good */
2161 if (scan
[0] == '_' && scan
[1] == '_')
2166 (*mangled
) += ARM_VTABLE_STRLEN
;
2167 while (**mangled
!= '\0')
2169 n
= consume_count (mangled
);
2170 string_prependn (declp
, *mangled
, n
);
2172 if ((*mangled
)[0] == '_' && (*mangled
)[1] == '_')
2174 string_prepend (declp
, "::");
2178 string_append (declp
, " virtual table");
2191 demangle_qualified -- demangle 'Q' qualified name strings
2196 demangle_qualified (struct work_stuff *, const char *mangled,
2197 string *result, int isfuncname, int append);
2201 Demangle a qualified name, such as "Q25Outer5Inner" which is
2202 the mangled form of "Outer::Inner". The demangled output is
2203 prepended or appended to the result string according to the
2204 state of the append flag.
2206 If isfuncname is nonzero, then the qualified name we are building
2207 is going to be used as a member function name, so if it is a
2208 constructor or destructor function, append an appropriate
2209 constructor or destructor name. I.E. for the above example,
2210 the result for use as a constructor is "Outer::Inner::Inner"
2211 and the result for use as a destructor is "Outer::Inner::~Inner".
2215 Numeric conversion is ASCII dependent (FIXME).
2220 demangle_qualified (work
, mangled
, result
, isfuncname
, append
)
2221 struct work_stuff
*work
;
2222 const char **mangled
;
2234 string_init (&temp
);
2236 if ((*mangled
)[0] == 'K')
2238 /* Squangling qualified name reuse */
2241 idx
= consume_count_with_underscores (mangled
);
2242 if (idx
== -1 || idx
> work
-> numk
)
2245 string_append (&temp
, work
-> ktypevec
[idx
]);
2248 switch ((*mangled
)[1])
2251 /* GNU mangled name with more than 9 classes. The count is preceded
2252 by an underscore (to distinguish it from the <= 9 case) and followed
2253 by an underscore. */
2255 qualifiers
= atoi (p
);
2256 if (!isdigit (*p
) || *p
== '0')
2259 /* Skip the digits. */
2260 while (isdigit (*p
))
2278 /* The count is in a single digit. */
2279 num
[0] = (*mangled
)[1];
2281 qualifiers
= atoi (num
);
2283 /* If there is an underscore after the digit, skip it. This is
2284 said to be for ARM-qualified names, but the ARM makes no
2285 mention of such an underscore. Perhaps cfront uses one. */
2286 if ((*mangled
)[2] == '_')
2301 /* Pick off the names and collect them in the temp buffer in the order
2302 in which they are found, separated by '::'. */
2304 while (qualifiers
-- > 0)
2307 if (*mangled
[0] == '_')
2308 *mangled
= *mangled
+ 1;
2309 if (*mangled
[0] == 't')
2311 success
= demangle_template(work
, mangled
, &temp
, 0, 1);
2312 if (!success
) break;
2314 else if (*mangled
[0] == 'X')
2316 success
= do_type (work
, mangled
, &temp
);
2317 if (!success
) break;
2319 else if (*mangled
[0] == 'K')
2323 idx
= consume_count_with_underscores (mangled
);
2324 if (idx
== -1 || idx
> work
->numk
)
2327 string_append (&temp
, work
->ktypevec
[idx
]);
2330 if (!success
) break;
2334 namelength
= consume_count (mangled
);
2335 if (strlen (*mangled
) < namelength
)
2337 /* Simple sanity check failed */
2341 string_appendn (&temp
, *mangled
, namelength
);
2342 *mangled
+= namelength
;
2347 remember_Ktype (work
, temp
.b
, LEN_STRING (&temp
));
2352 string_append (&temp
, "::");
2356 /* If we are using the result as a function name, we need to append
2357 the appropriate '::' separated constructor or destructor name.
2358 We do this here because this is the most convenient place, where
2359 we already have a pointer to the name and the length of the name. */
2361 if (isfuncname
&& (work
->constructor
& 1 || work
->destructor
& 1))
2363 string_append (&temp
, "::");
2364 if (work
-> destructor
& 1)
2366 string_append (&temp
, "~");
2368 string_appendn (&temp
, (*mangled
) - namelength
, namelength
);
2371 /* Now either prepend the temp buffer to the result, or append it,
2372 depending upon the state of the append flag. */
2376 string_appends (result
, &temp
);
2380 if (!STRING_EMPTY (result
))
2382 string_append (&temp
, "::");
2384 string_prepends (result
, &temp
);
2387 string_delete (&temp
);
2395 get_count -- convert an ascii count to integer, consuming tokens
2400 get_count (const char **type, int *count)
2404 Return 0 if no conversion is performed, 1 if a string is converted.
2408 get_count (type
, count
)
2415 if (!isdigit (**type
))
2421 *count
= **type
- '0';
2423 if (isdigit (**type
))
2433 while (isdigit (*p
));
2444 /* result will be initialised here; it will be freed on failure */
2447 do_type (work
, mangled
, result
)
2448 struct work_stuff
*work
;
2449 const char **mangled
;
2456 const char *remembered_type
;
2461 string_init (&btype
);
2462 string_init (&decl
);
2463 string_init (result
);
2467 while (success
&& !done
)
2473 /* A pointer type */
2477 string_prepend (&decl
, "*");
2480 /* A reference type */
2483 string_prepend (&decl
, "&");
2489 const char *p
= ++(*mangled
);
2491 string_prepend (&decl
, "(");
2492 string_append (&decl
, ")[");
2493 /* Copy anything up until the next underscore (the size of the
2495 while (**mangled
&& **mangled
!= '_')
2497 if (**mangled
== '_')
2499 string_appendn (&decl
, p
, *mangled
- p
);
2500 string_append (&decl
, "]");
2508 /* A back reference to a previously seen type */
2511 if (!get_count (mangled
, &n
) || n
>= work
-> ntypes
)
2517 remembered_type
= work
-> typevec
[n
];
2518 mangled
= &remembered_type
;
2525 if (!STRING_EMPTY (&decl
) && decl
.b
[0] == '*')
2527 string_prepend (&decl
, "(");
2528 string_append (&decl
, ")");
2530 /* After picking off the function args, we expect to either find the
2531 function return type (preceded by an '_') or the end of the
2533 if (!demangle_args (work
, mangled
, &decl
)
2534 || (**mangled
!= '_' && **mangled
!= '\0'))
2538 if (success
&& (**mangled
== '_'))
2550 member
= **mangled
== 'M';
2552 if (!isdigit (**mangled
) && **mangled
!= 't')
2558 string_append (&decl
, ")");
2559 string_prepend (&decl
, "::");
2560 if (isdigit (**mangled
))
2562 n
= consume_count (mangled
);
2563 if (strlen (*mangled
) < n
)
2568 string_prependn (&decl
, *mangled
, n
);
2574 string_init (&temp
);
2575 success
= demangle_template (work
, mangled
, &temp
, NULL
, 1);
2578 string_prependn (&decl
, temp
.b
, temp
.p
- temp
.b
);
2579 string_clear (&temp
);
2584 string_prepend (&decl
, "(");
2587 if (**mangled
== 'C')
2592 if (**mangled
== 'V')
2597 if (*(*mangled
)++ != 'F')
2603 if ((member
&& !demangle_args (work
, mangled
, &decl
))
2604 || **mangled
!= '_')
2610 if (! PRINT_ANSI_QUALIFIERS
)
2616 APPEND_BLANK (&decl
);
2617 string_append (&decl
, "const");
2621 APPEND_BLANK (&decl
);
2622 string_append (&decl
, "volatile");
2633 if ((*mangled)[1] == 'P')
2636 if (PRINT_ANSI_QUALIFIERS
)
2638 if (!STRING_EMPTY (&decl
))
2640 string_prepend (&decl
, " ");
2642 string_prepend (&decl
,
2643 (**mangled
) == 'C' ? "const" : "volatile");
2660 /* A qualified name, such as "Outer::Inner". */
2664 int btype
= register_Btype (work
);
2665 success
= demangle_qualified (work
, mangled
, result
, 0, 1);
2666 remember_Btype (work
, result
->b
, LEN_STRING (result
), btype
);
2671 /* A back reference to a previously seen squangled type */
2674 if (!get_count (mangled
, &n
) || n
>= work
-> numb
)
2678 string_append (result
, work
->btypevec
[n
]);
2684 /* A template parm. We substitute the corresponding argument. */
2689 idx
= consume_count_with_underscores (mangled
);
2692 || (work
->tmpl_argvec
&& idx
>= work
->ntmpl_args
)
2693 || consume_count_with_underscores (mangled
) == -1)
2699 if (work
->tmpl_argvec
)
2700 string_append (result
, work
->tmpl_argvec
[idx
]);
2704 sprintf(buf
, "T%d", idx
);
2705 string_append (result
, buf
);
2713 success
= demangle_fund_type (work
, mangled
, result
);
2719 if (!STRING_EMPTY (&decl
))
2721 string_append (result
, " ");
2722 string_appends (result
, &decl
);
2727 string_delete (result
);
2729 string_delete (&decl
);
2733 /* Given a pointer to a type string that represents a fundamental type
2734 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2735 string in which the demangled output is being built in RESULT, and
2736 the WORK structure, decode the types and add them to the result.
2741 "Sl" => "signed long"
2742 "CUs" => "const unsigned short"
2747 demangle_fund_type (work
, mangled
, result
)
2748 struct work_stuff
*work
;
2749 const char **mangled
;
2755 string_init (&btype
);
2757 /* First pick off any type qualifiers. There can be more than one. */
2765 if (PRINT_ANSI_QUALIFIERS
)
2767 APPEND_BLANK (result
);
2768 string_append (result
, "const");
2773 APPEND_BLANK (result
);
2774 string_append (result
, "unsigned");
2776 case 'S': /* signed char only */
2778 APPEND_BLANK (result
);
2779 string_append (result
, "signed");
2783 if (PRINT_ANSI_QUALIFIERS
)
2785 APPEND_BLANK (result
);
2786 string_append (result
, "volatile");
2791 APPEND_BLANK (result
);
2792 string_append (result
, "__complex");
2800 /* Now pick off the fundamental type. There can be only one. */
2809 APPEND_BLANK (result
);
2810 string_append (result
, "void");
2814 APPEND_BLANK (result
);
2815 string_append (result
, "long long");
2819 APPEND_BLANK (result
);
2820 string_append (result
, "long");
2824 APPEND_BLANK (result
);
2825 string_append (result
, "int");
2829 APPEND_BLANK (result
);
2830 string_append (result
, "short");
2834 APPEND_BLANK (result
);
2835 string_append (result
, "bool");
2839 APPEND_BLANK (result
);
2840 string_append (result
, "char");
2844 APPEND_BLANK (result
);
2845 string_append (result
, "wchar_t");
2849 APPEND_BLANK (result
);
2850 string_append (result
, "long double");
2854 APPEND_BLANK (result
);
2855 string_append (result
, "double");
2859 APPEND_BLANK (result
);
2860 string_append (result
, "float");
2864 if (!isdigit (**mangled
))
2870 /* An explicit type, such as "6mytype" or "7integer" */
2882 int bindex
= register_Btype (work
);
2884 string_init (&btype
);
2885 if (demangle_class_name (work
, mangled
, &btype
)) {
2886 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
2887 APPEND_BLANK (result
);
2888 string_appends (result
, &btype
);
2892 string_delete (&btype
);
2897 int bindex
= register_Btype (work
);
2898 success
= demangle_template (work
, mangled
, &btype
, 0, 1);
2899 remember_Btype (work
, btype
.b
, LEN_STRING (&btype
), bindex
);
2900 string_appends (result
, &btype
);
2911 /* `result' will be initialized in do_type; it will be freed on failure */
2914 do_arg (work
, mangled
, result
)
2915 struct work_stuff
*work
;
2916 const char **mangled
;
2919 const char *start
= *mangled
;
2921 if (!do_type (work
, mangled
, result
))
2927 remember_type (work
, start
, *mangled
- start
);
2933 remember_type (work
, start
, len
)
2934 struct work_stuff
*work
;
2940 if (work
-> ntypes
>= work
-> typevec_size
)
2942 if (work
-> typevec_size
== 0)
2944 work
-> typevec_size
= 3;
2946 = (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
2950 work
-> typevec_size
*= 2;
2952 = (char **) xrealloc ((char *)work
-> typevec
,
2953 sizeof (char *) * work
-> typevec_size
);
2956 tem
= xmalloc (len
+ 1);
2957 memcpy (tem
, start
, len
);
2959 work
-> typevec
[work
-> ntypes
++] = tem
;
2963 /* Remember a K type class qualifier. */
2965 remember_Ktype (work
, start
, len
)
2966 struct work_stuff
*work
;
2972 if (work
-> numk
>= work
-> ksize
)
2974 if (work
-> ksize
== 0)
2978 = (char **) xmalloc (sizeof (char *) * work
-> ksize
);
2984 = (char **) xrealloc ((char *)work
-> ktypevec
,
2985 sizeof (char *) * work
-> ksize
);
2988 tem
= xmalloc (len
+ 1);
2989 memcpy (tem
, start
, len
);
2991 work
-> ktypevec
[work
-> numk
++] = tem
;
2994 /* Register a B code, and get an index for it. B codes are registered
2995 as they are seen, rather than as they are completed, so map<temp<char> >
2996 registers map<temp<char> > as B0, and temp<char> as B1 */
2999 register_Btype (work
)
3000 struct work_stuff
*work
;
3004 if (work
-> numb
>= work
-> bsize
)
3006 if (work
-> bsize
== 0)
3010 = (char **) xmalloc (sizeof (char *) * work
-> bsize
);
3016 = (char **) xrealloc ((char *)work
-> btypevec
,
3017 sizeof (char *) * work
-> bsize
);
3020 ret
= work
-> numb
++;
3021 work
-> btypevec
[ret
] = NULL
;
3025 /* Store a value into a previously registered B code type. */
3028 remember_Btype (work
, start
, len
, index
)
3029 struct work_stuff
*work
;
3035 tem
= xmalloc (len
+ 1);
3036 memcpy (tem
, start
, len
);
3038 work
-> btypevec
[index
] = tem
;
3041 /* Lose all the info related to B and K type codes. */
3043 forget_B_and_K_types (work
)
3044 struct work_stuff
*work
;
3048 while (work
-> numk
> 0)
3050 i
= --(work
-> numk
);
3051 if (work
-> ktypevec
[i
] != NULL
)
3053 free (work
-> ktypevec
[i
]);
3054 work
-> ktypevec
[i
] = NULL
;
3058 while (work
-> numb
> 0)
3060 i
= --(work
-> numb
);
3061 if (work
-> btypevec
[i
] != NULL
)
3063 free (work
-> btypevec
[i
]);
3064 work
-> btypevec
[i
] = NULL
;
3068 /* Forget the remembered types, but not the type vector itself. */
3072 struct work_stuff
*work
;
3076 while (work
-> ntypes
> 0)
3078 i
= --(work
-> ntypes
);
3079 if (work
-> typevec
[i
] != NULL
)
3081 free (work
-> typevec
[i
]);
3082 work
-> typevec
[i
] = NULL
;
3087 /* Process the argument list part of the signature, after any class spec
3088 has been consumed, as well as the first 'F' character (if any). For
3091 "__als__3fooRT0" => process "RT0"
3092 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3094 DECLP must be already initialised, usually non-empty. It won't be freed
3097 Note that g++ differs significantly from ARM and lucid style mangling
3098 with regards to references to previously seen types. For example, given
3099 the source fragment:
3103 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3106 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3107 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3109 g++ produces the names:
3114 while lcc (and presumably other ARM style compilers as well) produces:
3116 foo__FiR3fooT1T2T1T2
3117 __ct__3fooFiR3fooT1T2T1T2
3119 Note that g++ bases it's type numbers starting at zero and counts all
3120 previously seen types, while lucid/ARM bases it's type numbers starting
3121 at one and only considers types after it has seen the 'F' character
3122 indicating the start of the function args. For lucid/ARM style, we
3123 account for this difference by discarding any previously seen types when
3124 we see the 'F' character, and subtracting one from the type number
3130 demangle_args (work
, mangled
, declp
)
3131 struct work_stuff
*work
;
3132 const char **mangled
;
3142 if (PRINT_ARG_TYPES
)
3144 string_append (declp
, "(");
3145 if (**mangled
== '\0')
3147 string_append (declp
, "void");
3151 while (**mangled
!= '_' && **mangled
!= '\0' && **mangled
!= 'e')
3153 if ((**mangled
== 'N') || (**mangled
== 'T'))
3155 temptype
= *(*mangled
)++;
3157 if (temptype
== 'N')
3159 if (!get_count (mangled
, &r
))
3168 if (ARM_DEMANGLING
&& work
-> ntypes
>= 10)
3170 /* If we have 10 or more types we might have more than a 1 digit
3171 index so we'll have to consume the whole count here. This
3172 will lose if the next thing is a type name preceded by a
3173 count but it's impossible to demangle that case properly
3174 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3175 Pc, ...)" or "(..., type12, char *, ...)" */
3176 if ((t
= consume_count(mangled
)) == 0)
3183 if (!get_count (mangled
, &t
))
3188 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3192 /* Validate the type index. Protect against illegal indices from
3193 malformed type strings. */
3194 if ((t
< 0) || (t
>= work
-> ntypes
))
3200 tem
= work
-> typevec
[t
];
3201 if (need_comma
&& PRINT_ARG_TYPES
)
3203 string_append (declp
, ", ");
3205 if (!do_arg (work
, &tem
, &arg
))
3209 if (PRINT_ARG_TYPES
)
3211 string_appends (declp
, &arg
);
3213 string_delete (&arg
);
3219 if (need_comma
& PRINT_ARG_TYPES
)
3221 string_append (declp
, ", ");
3223 if (!do_arg (work
, mangled
, &arg
))
3227 if (PRINT_ARG_TYPES
)
3229 string_appends (declp
, &arg
);
3231 string_delete (&arg
);
3236 if (**mangled
== 'e')
3239 if (PRINT_ARG_TYPES
)
3243 string_append (declp
, ",");
3245 string_append (declp
, "...");
3249 if (PRINT_ARG_TYPES
)
3251 string_append (declp
, ")");
3257 demangle_function_name (work
, mangled
, declp
, scan
)
3258 struct work_stuff
*work
;
3259 const char **mangled
;
3267 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
3268 string_need (declp
, 1);
3269 *(declp
-> p
) = '\0';
3271 /* Consume the function name, including the "__" separating the name
3272 from the signature. We are guaranteed that SCAN points to the
3275 (*mangled
) = scan
+ 2;
3277 if (LUCID_DEMANGLING
|| ARM_DEMANGLING
)
3280 /* See if we have an ARM style constructor or destructor operator.
3281 If so, then just record it, clear the decl, and return.
3282 We can't build the actual constructor/destructor decl until later,
3283 when we recover the class name from the signature. */
3285 if (strcmp (declp
-> b
, "__ct") == 0)
3287 work
-> constructor
+= 1;
3288 string_clear (declp
);
3291 else if (strcmp (declp
-> b
, "__dt") == 0)
3293 work
-> destructor
+= 1;
3294 string_clear (declp
);
3299 if (declp
->p
- declp
->b
>= 3
3300 && declp
->b
[0] == 'o'
3301 && declp
->b
[1] == 'p'
3302 && strchr (cplus_markers
, declp
->b
[2]) != NULL
)
3304 /* see if it's an assignment expression */
3305 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
3306 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
3308 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3310 int len
= declp
->p
- declp
->b
- 10;
3311 if (strlen (optable
[i
].in
) == len
3312 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
3314 string_clear (declp
);
3315 string_append (declp
, "operator");
3316 string_append (declp
, optable
[i
].out
);
3317 string_append (declp
, "=");
3324 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3326 int len
= declp
->p
- declp
->b
- 3;
3327 if (strlen (optable
[i
].in
) == len
3328 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
3330 string_clear (declp
);
3331 string_append (declp
, "operator");
3332 string_append (declp
, optable
[i
].out
);
3338 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type", 4) == 0
3339 && strchr (cplus_markers
, declp
->b
[4]) != NULL
)
3341 /* type conversion operator */
3343 if (do_type (work
, &tem
, &type
))
3345 string_clear (declp
);
3346 string_append (declp
, "operator ");
3347 string_appends (declp
, &type
);
3348 string_delete (&type
);
3351 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3352 && declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
3355 /* type conversion operator. */
3357 if (do_type (work
, &tem
, &type
))
3359 string_clear (declp
);
3360 string_append (declp
, "operator ");
3361 string_appends (declp
, &type
);
3362 string_delete (&type
);
3365 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
3366 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
3367 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
3369 if (declp
->b
[4] == '\0')
3372 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3374 if (strlen (optable
[i
].in
) == 2
3375 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
3377 string_clear (declp
);
3378 string_append (declp
, "operator");
3379 string_append (declp
, optable
[i
].out
);
3386 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
3389 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
3391 if (strlen (optable
[i
].in
) == 3
3392 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
3394 string_clear (declp
);
3395 string_append (declp
, "operator");
3396 string_append (declp
, optable
[i
].out
);
3405 /* a mini string-handling package */
3420 s
->p
= s
->b
= xmalloc (n
);
3423 else if (s
->e
- s
->p
< n
)
3428 s
->b
= xrealloc (s
->b
, n
);
3441 s
->b
= s
->e
= s
->p
= NULL
;
3449 s
->b
= s
->p
= s
->e
= NULL
;
3465 return (s
->b
== s
->p
);
3471 string_append (p
, s
)
3476 if (s
== NULL
|| *s
== '\0')
3480 memcpy (p
->p
, s
, n
);
3485 string_appends (p
, s
)
3494 memcpy (p
->p
, s
->b
, n
);
3500 string_appendn (p
, s
, n
)
3508 memcpy (p
->p
, s
, n
);
3514 string_prepend (p
, s
)
3518 if (s
!= NULL
&& *s
!= '\0')
3520 string_prependn (p
, s
, strlen (s
));
3525 string_prepends (p
, s
)
3530 string_prependn (p
, s
->b
, s
->p
- s
->b
);
3535 string_prependn (p
, s
, n
)
3545 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
3549 memcpy (p
->b
, s
, n
);
3554 /* To generate a standalone demangler program for testing purposes,
3555 just compile and link this file with -DMAIN and libiberty.a. When
3556 run, it demangles each command line arg, or each stdin string, and
3557 prints the result on stdout. */
3563 static char *program_name
;
3564 static char *program_version
= VERSION
;
3565 static int flags
= DMGL_PARAMS
| DMGL_ANSI
;
3567 static void demangle_it
PARAMS ((char *));
3568 static void usage
PARAMS ((FILE *, int));
3569 static void fatal
PARAMS ((char *));
3572 demangle_it (mangled_name
)
3577 result
= cplus_demangle (mangled_name
, flags
);
3580 printf ("%s\n", mangled_name
);
3584 printf ("%s\n", result
);
3590 usage (stream
, status
)
3595 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3596 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3597 [--help] [--version] [arg...]\n",
3602 #define MBUF_SIZE 512
3603 char mbuffer
[MBUF_SIZE
];
3605 /* Defined in the automatically-generated underscore.c. */
3606 extern int prepends_underscore
;
3608 int strip_underscore
= 0;
3610 static struct option long_options
[] = {
3611 {"strip-underscores", no_argument
, 0, '_'},
3612 {"format", required_argument
, 0, 's'},
3613 {"help", no_argument
, 0, 'h'},
3614 {"no-strip-underscores", no_argument
, 0, 'n'},
3615 {"version", no_argument
, 0, 'v'},
3616 {0, no_argument
, 0, 0}
3619 /* More 'friendly' abort that prints the line and file.
3620 config.h can #define abort fancy_abort if you like that sort of thing. */
3625 fatal ("Internal gcc abort.");
3636 program_name
= argv
[0];
3638 strip_underscore
= prepends_underscore
;
3640 while ((c
= getopt_long (argc
, argv
, "_ns:j", long_options
, (int *) 0)) != EOF
)
3650 strip_underscore
= 0;
3653 printf ("GNU %s version %s\n", program_name
, program_version
);
3656 strip_underscore
= 1;
3659 if (strcmp (optarg
, "gnu") == 0)
3661 current_demangling_style
= gnu_demangling
;
3663 else if (strcmp (optarg
, "lucid") == 0)
3665 current_demangling_style
= lucid_demangling
;
3667 else if (strcmp (optarg
, "arm") == 0)
3669 current_demangling_style
= arm_demangling
;
3673 fprintf (stderr
, "%s: unknown demangling style `%s'\n",
3674 program_name
, optarg
);
3683 for ( ; optind
< argc
; optind
++)
3685 demangle_it (argv
[optind
]);
3694 /* Try to read a label. */
3695 while (c
!= EOF
&& (isalnum(c
) || c
== '_' || c
== '$' || c
== '.'))
3697 if (i
>= MBUF_SIZE
-1)
3706 if (mbuffer
[0] == '.')
3708 if (strip_underscore
&& mbuffer
[skip_first
] == '_')
3716 result
= cplus_demangle (mbuffer
+ skip_first
, flags
);
3719 if (mbuffer
[0] == '.')
3721 fputs (result
, stdout
);
3725 fputs (mbuffer
, stdout
);
3742 fprintf (stderr
, "%s: %s\n", program_name
, str
);
3753 register char *value
= (char *) malloc (size
);
3755 fatal ("virtual memory exhausted");
3760 xrealloc (ptr
, size
)
3764 register char *value
= (char *) realloc (ptr
, size
);
3766 fatal ("virtual memory exhausted");