1 /* Demangler for GNU C++
2 Copyright 1989, 1991 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 program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* This is for g++ 1.95.03 (November 13 version). */
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 /* GDB-specific, FIXME. */
41 #if !defined (GNU_DEMANGLING) && !defined (ARM_DEMANGLING)
42 # define GNU_DEMANGLING 1
45 /* This is '$' on systems where the assembler can deal with that.
46 Where the assembler can't, it's '.' (but on many systems '.' is
47 used for other things). */
49 #if !defined (CPLUS_MARKER)
50 #define CPLUS_MARKER '$'
57 /* Stuff that is shared between sub-routines.
58 * Using a shared structure allows cplus_demangle to be reentrant. */
68 int static_type
; /* A static member function */
69 int const_type
; /* A const member function */
72 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
73 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
75 static const struct optable
81 "nw", " new", DMGL_ANSI
, /* new (1.92, ansi) */
82 "dl", " delete", DMGL_ANSI
, /* new (1.92, ansi) */
83 "new", " new", 0, /* old (1.91, and 1.x) */
84 "delete", " delete", 0, /* old (1.91, and 1.x) */
85 "as", "=", DMGL_ANSI
, /* ansi */
86 "ne", "!=", DMGL_ANSI
, /* old, ansi */
87 "eq", "==", DMGL_ANSI
, /* old, ansi */
88 "ge", ">=", DMGL_ANSI
, /* old, ansi */
89 "gt", ">", DMGL_ANSI
, /* old, ansi */
90 "le", "<=", DMGL_ANSI
, /* old, ansi */
91 "lt", "<", DMGL_ANSI
, /* old, ansi */
92 "plus", "+", 0, /* old */
93 "pl", "+", DMGL_ANSI
, /* ansi */
94 "apl", "+=", DMGL_ANSI
, /* ansi */
95 "minus", "-", 0, /* old */
96 "mi", "-", DMGL_ANSI
, /* ansi */
97 "ami", "-=", DMGL_ANSI
, /* ansi */
98 "mult", "*", 0, /* old */
99 "ml", "*", DMGL_ANSI
, /* ansi */
100 #ifdef ARM_DEMANGLING
101 "amu", "*=", DMGL_ANSI
, /* ansi */
103 "aml", "*=", DMGL_ANSI
, /* ansi */
105 "convert", "+", 0, /* old (unary +) */
106 "negate", "-", 0, /* old (unary -) */
107 "trunc_mod", "%", 0, /* old */
108 "md", "%", DMGL_ANSI
, /* ansi */
109 "amd", "%=", DMGL_ANSI
, /* ansi */
110 "trunc_div", "/", 0, /* old */
111 "dv", "/", DMGL_ANSI
, /* ansi */
112 "adv", "/=", DMGL_ANSI
, /* ansi */
113 "truth_andif", "&&", 0, /* old */
114 "aa", "&&", DMGL_ANSI
, /* ansi */
115 "truth_orif", "||", 0, /* old */
116 "oo", "||", DMGL_ANSI
, /* ansi */
117 "truth_not", "!", 0, /* old */
118 "nt", "!", DMGL_ANSI
, /* ansi */
119 "postincrement","++", 0, /* old */
120 "pp", "++", DMGL_ANSI
, /* ansi */
121 "postdecrement","--", 0, /* old */
122 "mm", "--", DMGL_ANSI
, /* ansi */
123 "bit_ior", "|", 0, /* old */
124 "or", "|", DMGL_ANSI
, /* ansi */
125 "aor", "|=", DMGL_ANSI
, /* ansi */
126 "bit_xor", "^", 0, /* old */
127 "er", "^", DMGL_ANSI
, /* ansi */
128 "aer", "^=", DMGL_ANSI
, /* ansi */
129 "bit_and", "&", 0, /* old */
130 "ad", "&", DMGL_ANSI
, /* ansi */
131 "aad", "&=", DMGL_ANSI
, /* ansi */
132 "bit_not", "~", 0, /* old */
133 "co", "~", DMGL_ANSI
, /* ansi */
134 "call", "()", 0, /* old */
135 "cl", "()", DMGL_ANSI
, /* ansi */
136 "alshift", "<<", 0, /* old */
137 "ls", "<<", DMGL_ANSI
, /* ansi */
138 "als", "<<=", DMGL_ANSI
, /* ansi */
139 "arshift", ">>", 0, /* old */
140 "rs", ">>", DMGL_ANSI
, /* ansi */
141 "ars", ">>=", DMGL_ANSI
, /* ansi */
142 "component", "->", 0, /* old */
143 #ifdef LUCID_DEMANGLING
144 "pt", "->", DMGL_ANSI
, /* ansi; Lucid C++ form */
146 "rf", "->", DMGL_ANSI
, /* ansi */
148 "indirect", "*", 0, /* old */
149 "method_call", "->()", 0, /* old */
150 "addr", "&", 0, /* old (unary &) */
151 "array", "[]", 0, /* old */
152 "vc", "[]", DMGL_ANSI
, /* ansi */
153 "compound", ", ", 0, /* old */
154 "cm", ", ", DMGL_ANSI
, /* ansi */
155 "cond", "?:", 0, /* old */
156 "cn", "?:", DMGL_ANSI
, /* psuedo-ansi */
157 "max", ">?", 0, /* old */
158 "mx", ">?", DMGL_ANSI
, /* psuedo-ansi */
159 "min", "<?", 0, /* old */
160 "mn", "<?", DMGL_ANSI
, /* psuedo-ansi */
161 "nop", "", 0, /* old (for operator=) */
162 "rm", "->*", DMGL_ANSI
, /* ansi */
166 typedef struct string
/* Beware: these aren't required to be */
167 { /* '\0' terminated. */
168 char *b
; /* pointer to start of string */
169 char *p
; /* pointer after last character */
170 char *e
; /* pointer after end of allocated space */
173 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
174 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
175 string_prepend(str, " ");}
176 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
177 string_append(str, " ");}
179 /* Prototypes for local functions */
182 mop_up
PARAMS ((string
*, struct work_stuff
*, int));
185 demangle_method_args
PARAMS ((string
*, const char **, struct work_stuff
*));
188 demangle_template
PARAMS ((string
*declp
, const char **, struct work_stuff
*));
191 demangle_qualified
PARAMS ((string
*, const char **, struct work_stuff
*));
194 demangle_class
PARAMS ((string
*, const char **, struct work_stuff
*));
197 demangle_fund_type
PARAMS ((const char **, string
*, struct work_stuff
*));
200 demangle_signature
PARAMS ((string
*, const char **, struct work_stuff
*));
203 demangle_prefix
PARAMS ((string
*, const char **, struct work_stuff
*));
206 gnu_special
PARAMS ((string
*, const char **, struct work_stuff
*));
209 string_need
PARAMS ((string
*, int));
212 string_delete
PARAMS ((string
*));
215 string_init
PARAMS ((string
*));
218 string_clear
PARAMS ((string
*));
221 string_empty
PARAMS ((string
*));
224 string_append
PARAMS ((string
*, const char *));
227 string_appends
PARAMS ((string
*, string
*));
230 string_appendn
PARAMS ((string
*, const char *, int));
233 string_prepend
PARAMS ((string
*, const char *));
236 string_prependn
PARAMS ((string
*, const char *, int));
239 get_count
PARAMS ((const char **, int *));
242 demangle_args
PARAMS ((string
*, const char **, struct work_stuff
*));
245 do_type
PARAMS ((const char **, string
*, struct work_stuff
*));
248 do_arg
PARAMS ((const char **, string
*, struct work_stuff
*));
251 demangle_function_name
PARAMS ((string
*, const char **, struct work_stuff
*,
255 remember_type
PARAMS ((const char *, int, struct work_stuff
*));
259 string_prepends
PARAMS ((string
*, string
*));
263 /* Takes operator name as e.g. "++" and returns mangled
264 operator name (e.g. "postincrement_expr"), or NULL if not found.
266 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
267 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
270 cplus_mangle_opname (opname
, options
)
277 len
= strlen (opname
);
278 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
280 if (strlen (optable
[i
].out
) == len
281 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
282 && memcmp (optable
[i
].out
, opname
, len
) == 0)
283 return ((char *)optable
[i
].in
);
288 /* char *cplus_demangle (const char *name, int options)
290 If NAME is a mangled function name produced by GNU C++, then
291 a pointer to a malloced string giving a C++ representation
292 of the name will be returned; otherwise NULL will be returned.
293 It is the caller's responsibility to free the string which
296 The OPTIONS arg may contain one or more of the following bits:
298 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
300 DMGL_PARAMS Function parameters are included.
304 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
305 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
306 cplus_demangle ("foo__1Ai", 0) => "A::foo"
308 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
309 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
310 cplus_demangle ("foo__1Afe", 0) => "A::foo"
312 Note that any leading underscores, or other such characters prepended by
313 the compilation system, are presumed to have already been stripped from
317 cplus_demangle (mangled
, options
)
323 struct work_stuff work
[1];
325 char *demangled
= NULL
;
327 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
329 (void) memset ((char *) work
, 0, sizeof (work
));
330 work
-> options
= options
;
333 success
= demangle_prefix (&decl
, &mangled
, work
);
334 if (success
&& (*mangled
!= '\0'))
336 success
= demangle_signature (&decl
, &mangled
, work
);
338 demangled
= mop_up (&decl
, work
, success
);
344 mop_up (declp
, work
, success
)
346 struct work_stuff
*work
;
350 char *demangled
= NULL
;
352 /* Discard the remembered types, if any. */
354 for (i
= 0; i
< work
-> ntypes
; i
++)
356 if (work
-> typevec
[i
] != NULL
)
358 free (work
-> typevec
[i
]);
361 if (work
-> typevec
!= NULL
)
363 free ((char *) work
-> typevec
);
366 /* If demangling was successful, ensure that the demangled string is null
367 terminated and return it. Otherwise, free the demangling decl. */
371 string_delete (declp
);
375 string_appendn (declp
, "", 1);
376 demangled
= declp
-> b
;
385 demangle_signature -- demangle the signature part of a mangled name
390 demangle_signature (string *declp, const char **mangled,
391 struct work_stuff *work);
395 Consume and demangle the signature portion of the mangled name.
397 DECLP is the string where demangled output is being built. At
398 entry it contains the demangled root name from the mangled name
399 prefix. I.E. either a demangled operator name or the root function
400 name. In some special cases, it may contain nothing.
402 *MANGLED points to the current unconsumed location in the mangled
403 name. As tokens are consumed and demangling is performed, the
404 pointer is updated to continuously point at the next token to
407 Demangling GNU style mangled names is nasty because there is no
408 explicit token that marks the start of the outermost function
413 demangle_signature (declp
, mangled
, work
)
415 const char **mangled
;
416 struct work_stuff
*work
;
420 #ifdef GNU_DEMANGLING
424 const char *premangle
;
428 premangle
= *mangled
;
431 while (success
&& (**mangled
!= '\0'))
436 success
= demangle_qualified (declp
, mangled
, work
);
437 #ifdef GNU_DEMANGLING
443 /* Static member function */
445 work
-> static_type
= 1;
449 /* a const member function */
451 work
-> const_type
= 1;
454 case '0': case '1': case '2': case '3': case '4':
455 case '5': case '6': case '7': case '8': case '9':
456 success
= demangle_class (declp
, mangled
, work
);
460 remember_type (premangle
, *mangled
- premangle
, work
);
463 #ifdef GNU_DEMANGLING
470 /* ARM style demangling includes a specific 'F' character after
471 the class name. For GNU style, it is just implied. So we can
472 safely just consume any 'F' at this point and be compatible
473 with either style. */
476 success
= demangle_args (declp
, mangled
, work
);
481 success
= demangle_template (declp
, mangled
, work
);
485 /* At the outermost level, we cannot have a return type specified,
486 so if we run into another '_' at this point we are dealing with
487 a mangled name that is either bogus, or has been mangled by
488 some algorithm we don't know how to deal with. So just
489 reject the entire demangling. */
494 #ifdef GNU_DEMANGLING
495 /* Assume we have stumbled onto the first outermost function
496 argument token, and start processing args. */
498 success
= demangle_args (declp
, mangled
, work
);
500 /* Non-GNU demanglers use a specific token to mark the start
501 of the outermost function argument tokens. Typically 'F',
502 for ARM-demangling, for example. So if we find something
503 we are not prepared for, it must be an error. */
508 #ifdef GNU_DEMANGLING
509 if (success
&& expect_func
)
512 success
= demangle_args (declp
, mangled
, work
);
516 if (success
&& !func_done
)
518 /* Even with ARM style demangling, sometimes there is no explicit
519 function argument tokens if the function takes no arguments. */
520 success
= demangle_args (declp
, mangled
, work
);
522 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
524 string_append (declp
, " static");
526 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
528 string_append (declp
, " const");
536 demangle_method_args (declp
, mangled
, work
)
538 const char **mangled
;
539 struct work_stuff
*work
;
543 if (work
-> static_type
)
545 string_append (declp
, *mangled
+ 1);
546 *mangled
+= strlen (*mangled
);
551 success
= demangle_args (declp
, mangled
, work
);
559 demangle_template (declp
, mangled
, work
)
561 const char **mangled
;
562 struct work_stuff
*work
;
580 string_init (&tname
);
581 string_init (&trawname
);
582 /* get template name */
583 if (!get_count (mangled
, &r
))
587 string_appendn (&tname
, *mangled
, r
);
588 string_appendn (&trawname
, *mangled
, r
);
589 string_appendn (&trawname
, "", 1);
591 string_append (&tname
, "<");
592 /* get size of template parameter list */
593 if (!get_count (mangled
, &r
))
597 for (i
= 0; i
< r
; i
++)
601 string_append (&tname
, ", ");
603 /* Z for type parameters */
604 if (**mangled
== 'Z')
607 success
= do_type (mangled
, &temp
, work
);
608 string_appendn (&temp
, "", 1);
611 string_append (&tname
, temp
.b
);
613 string_delete(&temp
);
621 /* otherwise, value parameter */
627 success
= do_type (mangled
, &temp
, work
);
628 string_appendn (&temp
, "", 1);
631 string_append (&tname
, temp
.b
);
633 string_delete(&temp
);
638 string_append (&tname
, "=");
639 while (*old_p
&& !done
)
645 done
= is_pointer
= 1;
647 case 'C': /* const */
648 case 'S': /* explicitly signed [char] */
649 case 'U': /* unsigned */
650 case 'V': /* volatile */
651 case 'F': /* function */
652 case 'M': /* member function */
656 case 'Q': /* repetition of following */
657 case 'T': /* remembered type */
663 case 'x': /* long long */
666 case 's': /* short */
668 done
= is_integral
= 1;
670 case 'r': /* long double */
671 case 'd': /* double */
672 case 'f': /* float */
681 if (**mangled
== 'm')
683 string_appendn (&tname
, "-", 1);
686 while (isdigit (**mangled
))
688 string_appendn (&tname
, *mangled
, 1);
694 if (**mangled
== 'm')
696 string_appendn (&tname
, "-", 1);
699 while (isdigit (**mangled
))
701 string_appendn (&tname
, *mangled
, 1);
704 if (**mangled
== '.') /* fraction */
706 string_appendn (&tname
, ".", 1);
708 while (isdigit (**mangled
))
710 string_appendn (&tname
, *mangled
, 1);
714 if (**mangled
== 'e') /* exponent */
716 string_appendn (&tname
, "e", 1);
718 while (isdigit (**mangled
))
720 string_appendn (&tname
, *mangled
, 1);
727 if (!get_count (mangled
, &symbol_len
))
732 string_appendn (&tname
, *mangled
, symbol_len
);
733 *mangled
+= symbol_len
;
738 string_append (&tname
, ">::");
739 if (work
-> destructor
)
741 string_append (&tname
, "~");
743 if (work
-> constructor
|| work
-> destructor
)
745 string_append (&tname
, trawname
.b
);
747 string_delete(&trawname
);
751 string_delete(&tname
);
755 string_prepend (declp
, tname
.b
);
756 string_delete (&tname
);
758 if (work
-> static_type
)
760 string_append (declp
, *mangled
+ 1);
761 *mangled
+= strlen (*mangled
);
766 success
= demangle_args (declp
, mangled
, work
);
775 demangle_class -- demangle a mangled class sequence
780 demangle_class (string *declp, const char **mangled,
781 struct work_stuff *work)
785 DECLP points to the buffer into which demangling is being done.
787 *MANGLED points to the current token to be demangled. On input,
788 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
789 On exit, it points to the next token after the mangled class on
790 success, or the first unconsumed token on failure.
792 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
793 we are demangling a constructor or destructor. In this case
794 we prepend "class::class" or "class::~class" to DECLP.
796 Otherwise, we prepend "class::" to the current DECLP.
798 Reset the constructor/destructor flags once they have been
799 "consumed". This allows demangle_class to be called later during
800 the same demangling, to do normal class demangling.
802 Returns 1 if demangling is successful, 0 otherwise.
807 demangle_class (declp
, mangled
, work
)
809 const char **mangled
;
810 struct work_stuff
*work
;
819 n
+= **mangled
- '0';
822 while (isdigit (**mangled
));
823 if (strlen (*mangled
) >= n
)
825 if (work
-> constructor
|| work
-> destructor
)
827 string_prependn (declp
, *mangled
, n
);
828 if (work
-> destructor
)
830 string_prepend (declp
, "~");
832 work
-> constructor
= work
-> destructor
= 0;
834 string_prepend (declp
, "::");
835 string_prependn (declp
, *mangled
, n
);
846 demangle_prefix -- consume the mangled name prefix and find signature
851 demangle_prefix (string *declp, const char **mangled,
852 struct work_stuff *work)
856 Consume and demangle the prefix of the mangled name.
858 DECLP points to the string buffer into which demangled output is
859 placed. On entry, the buffer is empty. On exit it contains
860 the root function name, the demangled operator name, or in some
861 special cases either nothing or the completely demangled result.
863 MANGLED points to the current pointer into the mangled name. As each
864 token of the mangled name is consumed, it is updated. Upon entry
865 the current mangled name pointer points to the first character of
866 the mangled name. Upon exit, it should point to the first character
867 of the signature if demangling was successful, or to the first
868 unconsumed character if demangling of the prefix was unsuccessful.
870 Returns 1 on success, 0 otherwise.
874 demangle_prefix (declp
, mangled
, work
)
876 const char **mangled
;
877 struct work_stuff
*work
;
882 if ((scan
= strstr (*mangled
, "__")) == NULL
)
884 success
= gnu_special (declp
, mangled
, work
);
886 else if (work
-> static_type
)
888 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
893 else if ((scan
== *mangled
) && (isdigit (scan
[2]) || (scan
[2] == 'Q')))
895 /* A GNU style constructor starts with "__<digit>" or "__Q". */
896 work
-> constructor
= 1;
899 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
901 /* Mangled name starts with "__". Skip over any leading '_' characters,
902 then find the next "__" that separates the prefix from the signature.
908 if ((scan
= strstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
910 /* No separator (I.E. "__not_mangled"), or empty signature
911 (I.E. "__not_mangled_either__") */
916 demangle_function_name (declp
, mangled
, work
, scan
);
919 else if (*(scan
+ 2) != '\0')
921 /* Mangled name does not start with "__" but does have one somewhere
922 in there with non empty stuff after it. Looks like a global
924 demangle_function_name (declp
, mangled
, work
, scan
);
928 /* Doesn't look like a mangled name */
935 gnu_special (declp
, mangled
, work
)
937 const char **mangled
;
938 struct work_stuff
*work
;
944 if ((*mangled
)[0] == '_'
945 && (*mangled
)[1] == CPLUS_MARKER
946 && (*mangled
)[2] == '_')
948 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
950 work
-> destructor
= 1;
952 else if (**mangled
!= '_' && (p
= strchr (*mangled
, CPLUS_MARKER
)) != NULL
)
955 /* static data member */
956 n
= strlen (*mangled
) + 2;
957 tem
= (char *) xmalloc (n
);
958 memcpy (tem
, *mangled
, p
- *mangled
);
959 strcpy (tem
+ (p
- *mangled
), "::");
960 strcpy (tem
+ (p
- *mangled
) + 2, p
+ 1);
963 else if ((*mangled
)[0] == '_'
964 && (*mangled
)[1] == 'v'
965 && (*mangled
)[2] == 't'
966 && (*mangled
)[3] == CPLUS_MARKER
)
968 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
969 and create the decl. Note that we consume the entire mangled
970 input string, which means that demangle_signature has no work
973 n
= strlen (*mangled
);
974 string_appendn (declp
, *mangled
, n
);
975 string_append (declp
, " virtual table");
985 /* Do a qualified name, such as "Q25Outer5Inner" for "Outer::Inner" */
988 demangle_qualified (declp
, mangled
, work
)
990 const char **mangled
;
991 struct work_stuff
*work
;
998 n
= (*mangled
)[1] - '0';
999 if (n
>= 0 && n
<= 9)
1001 if ((*mangled
)[2] == '_')
1007 string_init (&class);
1010 success
= do_type (mangled
, &tmp
, work
);
1011 string_appends (&class, &tmp
);
1012 string_append (&class, "::");
1013 if (n
== 0 && (work
-> constructor
|| work
-> destructor
))
1015 if (work
-> destructor
)
1017 string_append (&class, "~");
1019 string_appends (&class, &tmp
);
1021 string_delete (&tmp
);
1023 work
-> constructor
= work
-> destructor
= 0;
1024 string_prependn (declp
, class.b
, class.p
- class.b
);
1025 string_delete (&class);
1031 get_count (type
, count
)
1038 if (!isdigit (**type
))
1042 *count
= **type
- '0';
1044 /* see flush_repeats in cplus-method.c */
1045 if (isdigit (**type
))
1055 while (isdigit (*p
));
1065 /* result will be initialised here; it will be freed on failure */
1068 do_type (type
, result
, work
)
1071 struct work_stuff
*work
;
1077 const char *remembered_type
;
1081 string_init (&decl
);
1082 string_init (result
);
1086 while (success
&& !done
)
1091 /* A qualified name, such as "Outer::Inner". Note qualifier count
1092 is limited to a single digit (0-9 qualifiers). */
1094 n
= (*type
)[1] - '0';
1099 if ((*type
)[2] == '_') /* cfront style */
1106 do_type (type
, result
, work
);
1110 /* A pointer type */
1113 string_prepend (&decl
, "*");
1116 /* A reference type */
1119 string_prepend (&decl
, "&");
1122 /* A back reference to a previously seen type */
1125 if (!get_count (type
, &n
) || n
>= work
-> ntypes
)
1131 remembered_type
= work
-> typevec
[n
];
1132 type
= &remembered_type
;
1139 if (!STRING_EMPTY (&decl
) && decl
.b
[0] == '*')
1141 string_prepend (&decl
, "(");
1142 string_append (&decl
, ")");
1144 /* After picking off the function args, we expect to either find the
1145 function return type (preceded by an '_') or the end of the
1147 if (!demangle_args (&decl
, type
, work
)
1148 || (**type
!= '_' && **type
!= '\0'))
1152 if (success
&& (**type
== '_'))
1164 member
= **type
== 'M';
1166 if (!isdigit (**type
))
1178 while (isdigit (**type
));
1179 if (strlen (*type
) < n
)
1184 string_append (&decl
, ")");
1185 string_prepend (&decl
, "::");
1186 string_prependn (&decl
, *type
, n
);
1187 string_prepend (&decl
, "(");
1201 if (*(*type
)++ != 'F')
1207 if ((member
&& !demangle_args (&decl
, type
, work
))
1214 if (! PRINT_ANSI_QUALIFIERS
)
1220 APPEND_BLANK (&decl
);
1221 string_append (&decl
, "const");
1225 APPEND_BLANK (&decl
);
1226 string_append (&decl
, "volatile");
1232 if ((*type
)[1] == 'P')
1235 if (PRINT_ANSI_QUALIFIERS
)
1237 if (!STRING_EMPTY (&decl
))
1239 string_prepend (&decl
, " ");
1241 string_prepend (&decl
, "const");
1253 success
= demangle_fund_type (type
, result
, work
);
1257 if (!STRING_EMPTY (&decl
))
1259 string_append (result
, " ");
1260 string_appends (result
, &decl
);
1265 string_delete (result
);
1267 string_delete (&decl
);
1271 /* Given a pointer to a type string that represents a fundamental type
1272 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
1273 string in which the demangled output is being built in RESULT, and
1274 the WORK structure, decode the types and add them to the result.
1279 "Sl" => "signed long"
1280 "CUs" => "const unsigned short"
1285 demangle_fund_type (type
, result
, work
)
1288 struct work_stuff
*work
;
1294 /* First pick off any type qualifiers. There can be more than one. */
1302 if (PRINT_ANSI_QUALIFIERS
)
1304 APPEND_BLANK (result
);
1305 string_append (result
, "const");
1310 APPEND_BLANK (result
);
1311 string_append (result
, "unsigned");
1313 case 'S': /* signed char only */
1315 APPEND_BLANK (result
);
1316 string_append (result
, "signed");
1320 if (PRINT_ANSI_QUALIFIERS
)
1322 APPEND_BLANK (result
);
1323 string_append (result
, "volatile");
1332 /* Now pick off the fundamental type. There can be only one. */
1341 APPEND_BLANK (result
);
1342 string_append (result
, "void");
1346 APPEND_BLANK (result
);
1347 string_append (result
, "long long");
1351 APPEND_BLANK (result
);
1352 string_append (result
, "long");
1356 APPEND_BLANK (result
);
1357 string_append (result
, "int");
1361 APPEND_BLANK (result
);
1362 string_append (result
, "short");
1366 APPEND_BLANK (result
);
1367 string_append (result
, "char");
1371 APPEND_BLANK (result
);
1372 string_append (result
, "long double");
1376 APPEND_BLANK (result
);
1377 string_append (result
, "double");
1381 APPEND_BLANK (result
);
1382 string_append (result
, "float");
1386 if (!isdigit (**type
))
1392 /* An explicit type, such as "6mytype" or "7integer" */
1410 while (isdigit (**type
));
1411 if (strlen (*type
) < n
)
1416 APPEND_BLANK (result
);
1417 string_appendn (result
, *type
, n
);
1428 /* `result' will be initialized in do_type; it will be freed on failure */
1431 do_arg (type
, result
, work
)
1434 struct work_stuff
*work
;
1436 const char *start
= *type
;
1438 if (!do_type (type
, result
, work
))
1444 remember_type (start
, *type
- start
, work
);
1450 remember_type (start
, len
, work
)
1453 struct work_stuff
*work
;
1457 if (work
-> ntypes
>= work
-> typevec_size
)
1459 if (work
-> typevec_size
== 0)
1461 work
-> typevec_size
= 3;
1463 (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
1467 work
-> typevec_size
*= 2;
1469 (char **) xrealloc ((char *)work
-> typevec
,
1470 sizeof (char *) * work
-> typevec_size
);
1473 tem
= (char *) xmalloc (len
+ 1);
1474 memcpy (tem
, start
, len
);
1476 work
-> typevec
[work
-> ntypes
++] = tem
;
1479 /* Process the argument list part of the signature, after any class spec
1480 has been consumed, as well as the first 'F' character (if any). For
1483 "__als__3fooRT0" => process "RT0"
1484 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
1486 DECLP must be already initialised, usually non-empty. It won't be freed
1490 demangle_args (declp
, type
, work
)
1493 struct work_stuff
*work
;
1502 if (PRINT_ARG_TYPES
)
1504 string_append (declp
, "(");
1507 string_append (declp
, "void");
1511 while (**type
!= '_' && **type
!= '\0' && **type
!= 'e')
1513 if ((**type
== 'N') || (**type
== 'T'))
1515 temptype
= *(*type
)++;
1517 if (temptype
== 'N')
1519 if (!get_count (type
, &r
))
1528 if (!get_count (type
, &t
))
1532 #ifdef ARM_DEMANGLING
1535 if (t
>= work
-> ntypes
)
1541 tem
= work
-> typevec
[t
];
1542 if (need_comma
&& PRINT_ARG_TYPES
)
1544 string_append (declp
, ", ");
1546 if (!do_arg (&tem
, &arg
, work
))
1550 if (PRINT_ARG_TYPES
)
1552 string_appends (declp
, &arg
);
1554 string_delete (&arg
);
1560 if (need_comma
& PRINT_ARG_TYPES
)
1562 string_append (declp
, ", ");
1564 if (!do_arg (type
, &arg
, work
))
1568 if (PRINT_ARG_TYPES
)
1570 string_appends (declp
, &arg
);
1572 string_delete (&arg
);
1580 if (PRINT_ARG_TYPES
)
1584 string_append (declp
, ",");
1586 string_append (declp
, "...");
1590 if (PRINT_ARG_TYPES
)
1592 string_append (declp
, ")");
1598 demangle_function_name (declp
, mangled
, work
, scan
)
1600 const char **mangled
;
1601 struct work_stuff
*work
;
1609 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
1610 string_need (declp
, 1);
1611 *(declp
-> p
) = '\0';
1613 /* Consume the function name, including the "__" separating the name
1614 from the signature. We are guaranteed that SCAN points to the
1617 (*mangled
) = scan
+ 2;
1619 #ifdef ARM_DEMANGLING
1621 /* See if we have an ARM style constructor or destructor operator.
1622 If so, then just record it, clear the decl, and return.
1623 We can't build the actual constructor/destructor decl until later,
1624 when we recover the class name from the signature. */
1626 if (strcmp (declp
-> b
, "__ct") == 0)
1628 work
-> constructor
= 1;
1629 string_clear (declp
);
1632 else if (strcmp (declp
-> b
, "__dt") == 0)
1634 work
-> destructor
= 1;
1635 string_clear (declp
);
1641 if (declp
->p
- declp
->b
>= 3
1642 && declp
->b
[0] == 'o'
1643 && declp
->b
[1] == 'p'
1644 && declp
->b
[2] == CPLUS_MARKER
)
1646 /* see if it's an assignment expression */
1647 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
1648 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
1650 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
1652 len
= declp
->p
- declp
->b
- 10;
1653 if (strlen (optable
[i
].in
) == len
1654 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
1656 string_clear (declp
);
1657 string_append (declp
, "operator");
1658 string_append (declp
, optable
[i
].out
);
1659 string_append (declp
, "=");
1666 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
1668 int len
= declp
->p
- declp
->b
- 3;
1669 if (strlen (optable
[i
].in
) == len
1670 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
1672 string_clear (declp
);
1673 string_append (declp
, "operator");
1674 string_append (declp
, optable
[i
].out
);
1680 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type$", 5) == 0)
1682 /* type conversion operator */
1684 if (do_type (&tem
, &type
, work
))
1686 string_clear (declp
);
1687 string_append (declp
, "operator ");
1688 string_appends (declp
, &type
);
1689 string_delete (&type
);
1692 else if (declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
1695 /* type conversion operator. */
1697 if (do_type (&tem
, &type
, work
))
1699 string_clear (declp
);
1700 string_append (declp
, "operator ");
1701 string_appends (declp
, &type
);
1702 string_delete (&type
);
1705 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
1706 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
1707 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
1709 if (declp
->b
[4] == '\0')
1712 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
1714 if (strlen (optable
[i
].in
) == 2
1715 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
1717 string_clear (declp
);
1718 string_append (declp
, "operator");
1719 string_append (declp
, optable
[i
].out
);
1726 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
1729 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
1731 if (strlen (optable
[i
].in
) == 3
1732 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
1734 string_clear (declp
);
1735 string_append (declp
, "operator");
1736 string_append (declp
, optable
[i
].out
);
1745 /* a mini string-handling package */
1760 s
->p
= s
->b
= (char *) xmalloc (n
);
1763 else if (s
->e
- s
->p
< n
)
1768 s
->b
= (char *) xrealloc (s
->b
, n
);
1781 s
->b
= s
->e
= s
->p
= NULL
;
1789 s
->b
= s
->p
= s
->e
= NULL
;
1803 return (s
->b
== s
->p
);
1807 string_append (p
, s
)
1812 if (s
== NULL
|| *s
== '\0')
1816 memcpy (p
->p
, s
, n
);
1821 string_appends (p
, s
)
1830 memcpy (p
->p
, s
->b
, n
);
1836 string_appendn (p
, s
, n
)
1844 memcpy (p
->p
, s
, n
);
1850 string_prepend (p
, s
)
1854 if (s
!= NULL
&& *s
!= '\0')
1856 string_prependn (p
, s
, strlen (s
));
1862 string_prepends (p
, s
)
1867 string_prependn (p
, s
->b
, s
->p
- s
->b
);
1873 string_prependn (p
, s
, n
)
1883 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
1887 memcpy (p
->b
, s
, n
);
1892 /* To generate a standalone demangler program for testing purposes, just
1893 compile and link this file with -DMAIN. When run, it demangles each
1894 command line arg, or each stdin string, and prints the result on stdout. */
1899 demangle_it (mangled_name
)
1904 result
= cplus_demangle (mangled_name
, DMGL_PARAMS
| DMGL_ANSI
);
1907 printf ("%s\n", mangled_name
);
1911 printf ("%s\n", result
);
1922 if ((newmem
= malloc ((int) size
)) == NULL
)
1924 fprintf (stderr
, "\nCan't allocate %u bytes\n", size
);
1931 xrealloc (oldmem
, size
)
1937 if ((newmem
= realloc ((char *) oldmem
, (int) size
)) == NULL
)
1939 fprintf (stderr
, "\nCan't reallocate %u bytes\n", size
);
1949 char mangled_name
[128];
1958 demangle_it (*argv
);
1963 while (gets (mangled_name
))
1965 demangle_it (mangled_name
);
This page took 0.084813 seconds and 5 git commands to generate.