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. */
35 #if !defined (GNU_DEMANGLING) && !defined (ARM_DEMANGLING)
36 # define GNU_DEMANGLING 1
39 /* This is '$' on systems where the assembler can deal with that.
40 Where the assembler can't, it's '.' (but on many systems '.' is
41 used for other things). */
43 #if !defined (CPLUS_MARKER)
44 #define CPLUS_MARKER '$'
51 /* Stuff that is shared between sub-routines.
52 * Using a shared structure allows cplus_demangle to be reentrant. */
62 int static_type
; /* A static member function */
63 int const_type
; /* A const member function */
66 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
67 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
69 static const struct optable
75 "nw", " new", DMGL_ANSI
, /* new (1.92, ansi) */
76 "dl", " delete", DMGL_ANSI
, /* new (1.92, ansi) */
77 "new", " new", 0, /* old (1.91, and 1.x) */
78 "delete", " delete", 0, /* old (1.91, and 1.x) */
79 "as", "=", DMGL_ANSI
, /* ansi */
80 "ne", "!=", DMGL_ANSI
, /* old, ansi */
81 "eq", "==", DMGL_ANSI
, /* old, ansi */
82 "ge", ">=", DMGL_ANSI
, /* old, ansi */
83 "gt", ">", DMGL_ANSI
, /* old, ansi */
84 "le", "<=", DMGL_ANSI
, /* old, ansi */
85 "lt", "<", DMGL_ANSI
, /* old, ansi */
86 "plus", "+", 0, /* old */
87 "pl", "+", DMGL_ANSI
, /* ansi */
88 "apl", "+=", DMGL_ANSI
, /* ansi */
89 "minus", "-", 0, /* old */
90 "mi", "-", DMGL_ANSI
, /* ansi */
91 "ami", "-=", DMGL_ANSI
, /* ansi */
92 "mult", "*", 0, /* old */
93 "ml", "*", DMGL_ANSI
, /* ansi */
95 "amu", "*=", DMGL_ANSI
, /* ansi */
97 "aml", "*=", DMGL_ANSI
, /* ansi */
99 "convert", "+", 0, /* old (unary +) */
100 "negate", "-", 0, /* old (unary -) */
101 "trunc_mod", "%", 0, /* old */
102 "md", "%", DMGL_ANSI
, /* ansi */
103 "amd", "%=", DMGL_ANSI
, /* ansi */
104 "trunc_div", "/", 0, /* old */
105 "dv", "/", DMGL_ANSI
, /* ansi */
106 "adv", "/=", DMGL_ANSI
, /* ansi */
107 "truth_andif", "&&", 0, /* old */
108 "aa", "&&", DMGL_ANSI
, /* ansi */
109 "truth_orif", "||", 0, /* old */
110 "oo", "||", DMGL_ANSI
, /* ansi */
111 "truth_not", "!", 0, /* old */
112 "nt", "!", DMGL_ANSI
, /* ansi */
113 "postincrement","++", 0, /* old */
114 "pp", "++", DMGL_ANSI
, /* ansi */
115 "postdecrement","--", 0, /* old */
116 "mm", "--", DMGL_ANSI
, /* ansi */
117 "bit_ior", "|", 0, /* old */
118 "or", "|", DMGL_ANSI
, /* ansi */
119 "aor", "|=", DMGL_ANSI
, /* ansi */
120 "bit_xor", "^", 0, /* old */
121 "er", "^", DMGL_ANSI
, /* ansi */
122 "aer", "^=", DMGL_ANSI
, /* ansi */
123 "bit_and", "&", 0, /* old */
124 "ad", "&", DMGL_ANSI
, /* ansi */
125 "aad", "&=", DMGL_ANSI
, /* ansi */
126 "bit_not", "~", 0, /* old */
127 "co", "~", DMGL_ANSI
, /* ansi */
128 "call", "()", 0, /* old */
129 "cl", "()", DMGL_ANSI
, /* ansi */
130 "alshift", "<<", 0, /* old */
131 "ls", "<<", DMGL_ANSI
, /* ansi */
132 "als", "<<=", DMGL_ANSI
, /* ansi */
133 "arshift", ">>", 0, /* old */
134 "rs", ">>", DMGL_ANSI
, /* ansi */
135 "ars", ">>=", DMGL_ANSI
, /* ansi */
136 "component", "->", 0, /* old */
137 #ifdef LUCID_DEMANGLING
138 "pt", "->", DMGL_ANSI
, /* ansi; Lucid C++ form */
140 "rf", "->", DMGL_ANSI
, /* ansi */
142 "indirect", "*", 0, /* old */
143 "method_call", "->()", 0, /* old */
144 "addr", "&", 0, /* old (unary &) */
145 "array", "[]", 0, /* old */
146 "vc", "[]", DMGL_ANSI
, /* ansi */
147 "compound", ", ", 0, /* old */
148 "cm", ", ", DMGL_ANSI
, /* ansi */
149 "cond", "?:", 0, /* old */
150 "cn", "?:", DMGL_ANSI
, /* psuedo-ansi */
151 "max", ">?", 0, /* old */
152 "mx", ">?", DMGL_ANSI
, /* psuedo-ansi */
153 "min", "<?", 0, /* old */
154 "mn", "<?", DMGL_ANSI
, /* psuedo-ansi */
155 "nop", "", 0, /* old (for operator=) */
156 "rm", "->*", DMGL_ANSI
, /* ansi */
160 typedef struct string
/* Beware: these aren't required to be */
161 { /* '\0' terminated. */
162 char *b
; /* pointer to start of string */
163 char *p
; /* pointer after last character */
164 char *e
; /* pointer after end of allocated space */
167 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
168 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
169 string_prepend(str, " ");}
170 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
171 string_append(str, " ");}
173 /* Prototypes for local functions */
176 mop_up
PARAMS ((string
*, struct work_stuff
*, int));
179 demangle_method_args
PARAMS ((string
*, const char **, struct work_stuff
*));
182 demangle_template
PARAMS ((string
*declp
, const char **, struct work_stuff
*));
185 demangle_qualified
PARAMS ((string
*, const char **, struct work_stuff
*));
188 demangle_class
PARAMS ((string
*, const char **, struct work_stuff
*));
191 demangle_fund_type
PARAMS ((const char **, string
*, struct work_stuff
*));
194 demangle_signature
PARAMS ((string
*, const char **, struct work_stuff
*));
197 demangle_prefix
PARAMS ((string
*, const char **, struct work_stuff
*));
200 gnu_special
PARAMS ((string
*, const char **, struct work_stuff
*));
203 string_need
PARAMS ((string
*, int));
206 string_delete
PARAMS ((string
*));
209 string_init
PARAMS ((string
*));
212 string_clear
PARAMS ((string
*));
215 string_empty
PARAMS ((string
*));
218 string_append
PARAMS ((string
*, const char *));
221 string_appends
PARAMS ((string
*, string
*));
224 string_appendn
PARAMS ((string
*, const char *, int));
227 string_prepend
PARAMS ((string
*, const char *));
230 string_prependn
PARAMS ((string
*, const char *, int));
233 get_count
PARAMS ((const char **, int *));
236 demangle_args
PARAMS ((string
*, const char **, struct work_stuff
*));
239 do_type
PARAMS ((const char **, string
*, struct work_stuff
*));
242 do_arg
PARAMS ((const char **, string
*, struct work_stuff
*));
245 demangle_function_name
PARAMS ((string
*, const char **, struct work_stuff
*,
249 remember_type
PARAMS ((const char *, int, struct work_stuff
*));
253 string_prepends
PARAMS ((string
*, string
*));
257 /* Takes operator name as e.g. "++" and returns mangled
258 operator name (e.g. "postincrement_expr"), or NULL if not found.
260 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
261 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
264 cplus_mangle_opname (opname
, options
)
271 len
= strlen (opname
);
272 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
274 if (strlen (optable
[i
].out
) == len
275 && (options
& DMGL_ANSI
) == (optable
[i
].flags
& DMGL_ANSI
)
276 && memcmp (optable
[i
].out
, opname
, len
) == 0)
277 return ((char *)optable
[i
].in
);
282 /* char *cplus_demangle (const char *name, int options)
284 If NAME is a mangled function name produced by GNU C++, then
285 a pointer to a malloced string giving a C++ representation
286 of the name will be returned; otherwise NULL will be returned.
287 It is the caller's responsibility to free the string which
290 The OPTIONS arg may contain one or more of the following bits:
292 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
294 DMGL_PARAMS Function parameters are included.
298 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
299 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
300 cplus_demangle ("foo__1Ai", 0) => "A::foo"
302 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
303 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
304 cplus_demangle ("foo__1Afe", 0) => "A::foo"
306 Note that any leading underscores, or other such characters prepended by
307 the compilation system, are presumed to have already been stripped from
311 cplus_demangle (mangled
, options
)
317 struct work_stuff work
[1];
319 char *demangled
= NULL
;
321 if ((mangled
!= NULL
) && (*mangled
!= '\0'))
323 (void) memset ((char *) work
, 0, sizeof (work
));
324 work
-> options
= options
;
327 success
= demangle_prefix (&decl
, &mangled
, work
);
328 if (success
&& (*mangled
!= '\0'))
330 success
= demangle_signature (&decl
, &mangled
, work
);
332 demangled
= mop_up (&decl
, work
, success
);
338 mop_up (declp
, work
, success
)
340 struct work_stuff
*work
;
344 char *demangled
= NULL
;
346 /* Discard the remembered types, if any. */
348 for (i
= 0; i
< work
-> ntypes
; i
++)
350 if (work
-> typevec
[i
] != NULL
)
352 free (work
-> typevec
[i
]);
355 if (work
-> typevec
!= NULL
)
357 free ((char *) work
-> typevec
);
360 /* If demangling was successful, ensure that the demangled string is null
361 terminated and return it. Otherwise, free the demangling decl. */
365 string_delete (declp
);
369 string_appendn (declp
, "", 1);
370 demangled
= declp
-> b
;
379 demangle_signature -- demangle the signature part of a mangled name
384 demangle_signature (string *declp, const char **mangled,
385 struct work_stuff *work);
389 Consume and demangle the signature portion of the mangled name.
391 DECLP is the string where demangled output is being built. At
392 entry it contains the demangled root name from the mangled name
393 prefix. I.E. either a demangled operator name or the root function
394 name. In some special cases, it may contain nothing.
396 *MANGLED points to the current unconsumed location in the mangled
397 name. As tokens are consumed and demangling is performed, the
398 pointer is updated to continuously point at the next token to
401 Demangling GNU style mangled names is nasty because there is no
402 explicit token that marks the start of the outermost function
407 demangle_signature (declp
, mangled
, work
)
409 const char **mangled
;
410 struct work_stuff
*work
;
414 #ifdef GNU_DEMANGLING
418 const char *premangle
;
422 premangle
= *mangled
;
425 while (success
&& (**mangled
!= '\0'))
430 success
= demangle_qualified (declp
, mangled
, work
);
431 #ifdef GNU_DEMANGLING
437 /* Static member function */
439 work
-> static_type
= 1;
443 /* a const member function */
445 work
-> const_type
= 1;
448 case '0': case '1': case '2': case '3': case '4':
449 case '5': case '6': case '7': case '8': case '9':
450 success
= demangle_class (declp
, mangled
, work
);
454 remember_type (premangle
, *mangled
- premangle
, work
);
457 #ifdef GNU_DEMANGLING
464 /* ARM style demangling includes a specific 'F' character after
465 the class name. For GNU style, it is just implied. So we can
466 safely just consume any 'F' at this point and be compatible
467 with either style. */
470 success
= demangle_args (declp
, mangled
, work
);
475 success
= demangle_template (declp
, mangled
, work
);
479 /* At the outermost level, we cannot have a return type specified,
480 so if we run into another '_' at this point we are dealing with
481 a mangled name that is either bogus, or has been mangled by
482 some algorithm we don't know how to deal with. So just
483 reject the entire demangling. */
488 #ifdef GNU_DEMANGLING
489 /* Assume we have stumbled onto the first outermost function
490 argument token, and start processing args. */
492 success
= demangle_args (declp
, mangled
, work
);
494 /* Non-GNU demanglers use a specific token to mark the start
495 of the outermost function argument tokens. Typically 'F',
496 for ARM-demangling, for example. So if we find something
497 we are not prepared for, it must be an error. */
502 #ifdef GNU_DEMANGLING
503 if (success
&& expect_func
)
506 success
= demangle_args (declp
, mangled
, work
);
510 if (success
&& !func_done
)
512 /* Even with ARM style demangling, sometimes there is no explicit
513 function argument tokens if the function takes no arguments. */
514 success
= demangle_args (declp
, mangled
, work
);
516 if (success
&& work
-> static_type
&& PRINT_ARG_TYPES
)
518 string_append (declp
, " static");
520 if (success
&& work
-> const_type
&& PRINT_ARG_TYPES
)
522 string_append (declp
, " const");
530 demangle_method_args (declp
, mangled
, work
)
532 const char **mangled
;
533 struct work_stuff
*work
;
537 if (work
-> static_type
)
539 string_append (declp
, *mangled
+ 1);
540 *mangled
+= strlen (*mangled
);
545 success
= demangle_args (declp
, mangled
, work
);
553 demangle_template (declp
, mangled
, work
)
555 const char **mangled
;
556 struct work_stuff
*work
;
574 string_init (&tname
);
575 string_init (&trawname
);
576 /* get template name */
577 if (!get_count (mangled
, &r
))
581 string_appendn (&tname
, *mangled
, r
);
582 string_appendn (&trawname
, *mangled
, r
);
583 string_appendn (&trawname
, "", 1);
585 string_append (&tname
, "<");
586 /* get size of template parameter list */
587 if (!get_count (mangled
, &r
))
591 for (i
= 0; i
< r
; i
++)
595 string_append (&tname
, ", ");
597 /* Z for type parameters */
598 if (**mangled
== 'Z')
601 success
= do_type (mangled
, &temp
, work
);
602 string_appendn (&temp
, "", 1);
605 string_append (&tname
, temp
.b
);
607 string_delete(&temp
);
615 /* otherwise, value parameter */
621 success
= do_type (mangled
, &temp
, work
);
622 string_appendn (&temp
, "", 1);
625 string_append (&tname
, temp
.b
);
627 string_delete(&temp
);
632 string_append (&tname
, "=");
633 while (*old_p
&& !done
)
639 done
= is_pointer
= 1;
641 case 'C': /* const */
642 case 'S': /* explicitly signed [char] */
643 case 'U': /* unsigned */
644 case 'V': /* volatile */
645 case 'F': /* function */
646 case 'M': /* member function */
650 case 'Q': /* repetition of following */
651 case 'T': /* remembered type */
657 case 'x': /* long long */
660 case 's': /* short */
662 done
= is_integral
= 1;
664 case 'r': /* long double */
665 case 'd': /* double */
666 case 'f': /* float */
675 if (**mangled
== 'm')
677 string_appendn (&tname
, "-", 1);
680 while (isdigit (**mangled
))
682 string_appendn (&tname
, *mangled
, 1);
688 if (**mangled
== 'm')
690 string_appendn (&tname
, "-", 1);
693 while (isdigit (**mangled
))
695 string_appendn (&tname
, *mangled
, 1);
698 if (**mangled
== '.') /* fraction */
700 string_appendn (&tname
, ".", 1);
702 while (isdigit (**mangled
))
704 string_appendn (&tname
, *mangled
, 1);
708 if (**mangled
== 'e') /* exponent */
710 string_appendn (&tname
, "e", 1);
712 while (isdigit (**mangled
))
714 string_appendn (&tname
, *mangled
, 1);
721 if (!get_count (mangled
, &symbol_len
))
726 string_appendn (&tname
, *mangled
, symbol_len
);
727 *mangled
+= symbol_len
;
732 string_append (&tname
, ">::");
733 if (work
-> destructor
)
735 string_append (&tname
, "~");
737 if (work
-> constructor
|| work
-> destructor
)
739 string_append (&tname
, trawname
.b
);
741 string_delete(&trawname
);
745 string_delete(&tname
);
749 string_prepend (declp
, tname
.b
);
750 string_delete (&tname
);
752 if (work
-> static_type
)
754 string_append (declp
, *mangled
+ 1);
755 *mangled
+= strlen (*mangled
);
760 success
= demangle_args (declp
, mangled
, work
);
769 demangle_class -- demangle a mangled class sequence
774 demangle_class (string *declp, const char **mangled,
775 struct work_stuff *work)
779 DECLP points to the buffer into which demangling is being done.
781 *MANGLED points to the current token to be demangled. On input,
782 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
783 On exit, it points to the next token after the mangled class on
784 success, or the first unconsumed token on failure.
786 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
787 we are demangling a constructor or destructor. In this case
788 we prepend "class::class" or "class::~class" to DECLP.
790 Otherwise, we prepend "class::" to the current DECLP.
792 Reset the constructor/destructor flags once they have been
793 "consumed". This allows demangle_class to be called later during
794 the same demangling, to do normal class demangling.
796 Returns 1 if demangling is successful, 0 otherwise.
801 demangle_class (declp
, mangled
, work
)
803 const char **mangled
;
804 struct work_stuff
*work
;
813 n
+= **mangled
- '0';
816 while (isdigit (**mangled
));
817 if (strlen (*mangled
) >= n
)
819 if (work
-> constructor
|| work
-> destructor
)
821 string_prependn (declp
, *mangled
, n
);
822 if (work
-> destructor
)
824 string_prepend (declp
, "~");
826 work
-> constructor
= work
-> destructor
= 0;
828 string_prepend (declp
, "::");
829 string_prependn (declp
, *mangled
, n
);
840 demangle_prefix -- consume the mangled name prefix and find signature
845 demangle_prefix (string *declp, const char **mangled,
846 struct work_stuff *work)
850 Consume and demangle the prefix of the mangled name.
852 DECLP points to the string buffer into which demangled output is
853 placed. On entry, the buffer is empty. On exit it contains
854 the root function name, the demangled operator name, or in some
855 special cases either nothing or the completely demangled result.
857 MANGLED points to the current pointer into the mangled name. As each
858 token of the mangled name is consumed, it is updated. Upon entry
859 the current mangled name pointer points to the first character of
860 the mangled name. Upon exit, it should point to the first character
861 of the signature if demangling was successful, or to the first
862 unconsumed character if demangling of the prefix was unsuccessful.
864 Returns 1 on success, 0 otherwise.
868 demangle_prefix (declp
, mangled
, work
)
870 const char **mangled
;
871 struct work_stuff
*work
;
876 if ((scan
= strstr (*mangled
, "__")) == NULL
)
878 success
= gnu_special (declp
, mangled
, work
);
880 else if (work
-> static_type
)
882 if (!isdigit (scan
[0]) && (scan
[0] != 't'))
887 else if ((scan
== *mangled
) && (isdigit (scan
[2]) || (scan
[2] == 'Q')))
889 /* A GNU style constructor starts with "__<digit>" or "__Q". */
890 work
-> constructor
= 1;
893 else if ((scan
== *mangled
) && !isdigit (scan
[2]) && (scan
[2] != 't'))
895 /* Mangled name starts with "__". Skip over any leading '_' characters,
896 then find the next "__" that separates the prefix from the signature.
902 if ((scan
= strstr (scan
, "__")) == NULL
|| (*(scan
+ 2) == '\0'))
904 /* No separator (I.E. "__not_mangled"), or empty signature
905 (I.E. "__not_mangled_either__") */
910 demangle_function_name (declp
, mangled
, work
, scan
);
913 else if (*(scan
+ 2) != '\0')
915 /* Mangled name does not start with "__" but does have one somewhere
916 in there with non empty stuff after it. Looks like a global
918 demangle_function_name (declp
, mangled
, work
, scan
);
922 /* Doesn't look like a mangled name */
929 gnu_special (declp
, mangled
, work
)
931 const char **mangled
;
932 struct work_stuff
*work
;
938 if ((*mangled
)[0] == '_'
939 && (*mangled
)[1] == CPLUS_MARKER
940 && (*mangled
)[2] == '_')
942 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
944 work
-> destructor
= 1;
946 else if (**mangled
!= '_' && (p
= strchr (*mangled
, CPLUS_MARKER
)) != NULL
)
949 /* static data member */
950 n
= strlen (*mangled
) + 2;
951 tem
= (char *) xmalloc (n
);
952 memcpy (tem
, *mangled
, p
- *mangled
);
953 strcpy (tem
+ (p
- *mangled
), "::");
954 strcpy (tem
+ (p
- *mangled
) + 2, p
+ 1);
957 else if ((*mangled
)[0] == '_'
958 && (*mangled
)[1] == 'v'
959 && (*mangled
)[2] == 't'
960 && (*mangled
)[3] == CPLUS_MARKER
)
962 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
963 and create the decl. Note that we consume the entire mangled
964 input string, which means that demangle_signature has no work
967 n
= strlen (*mangled
);
968 string_appendn (declp
, *mangled
, n
);
969 string_append (declp
, " virtual table");
979 /* Do a qualified name, such as "Q25Outer5Inner" for "Outer::Inner" */
982 demangle_qualified (declp
, mangled
, work
)
984 const char **mangled
;
985 struct work_stuff
*work
;
992 n
= (*mangled
)[1] - '0';
993 if (n
>= 0 && n
<= 9)
995 if ((*mangled
)[2] == '_')
1001 string_init (&class);
1004 success
= do_type (mangled
, &tmp
, work
);
1005 string_appends (&class, &tmp
);
1006 string_append (&class, "::");
1007 if (n
== 0 && (work
-> constructor
|| work
-> destructor
))
1009 if (work
-> destructor
)
1011 string_append (&class, "~");
1013 string_appends (&class, &tmp
);
1015 string_delete (&tmp
);
1017 work
-> constructor
= work
-> destructor
= 0;
1018 string_prependn (declp
, class.b
, class.p
- class.b
);
1019 string_delete (&class);
1025 get_count (type
, count
)
1032 if (!isdigit (**type
))
1036 *count
= **type
- '0';
1038 /* see flush_repeats in cplus-method.c */
1039 if (isdigit (**type
))
1049 while (isdigit (*p
));
1059 /* result will be initialised here; it will be freed on failure */
1062 do_type (type
, result
, work
)
1065 struct work_stuff
*work
;
1071 const char *remembered_type
;
1075 string_init (&decl
);
1076 string_init (result
);
1080 while (success
&& !done
)
1085 /* A qualified name, such as "Outer::Inner". Note qualifier count
1086 is limited to a single digit (0-9 qualifiers). */
1088 n
= (*type
)[1] - '0';
1093 if ((*type
)[2] == '_') /* cfront style */
1100 do_type (type
, result
, work
);
1104 /* A pointer type */
1107 string_prepend (&decl
, "*");
1110 /* A reference type */
1113 string_prepend (&decl
, "&");
1116 /* A back reference to a previously seen type */
1119 if (!get_count (type
, &n
) || n
>= work
-> ntypes
)
1125 remembered_type
= work
-> typevec
[n
];
1126 type
= &remembered_type
;
1133 if (!STRING_EMPTY (&decl
) && decl
.b
[0] == '*')
1135 string_prepend (&decl
, "(");
1136 string_append (&decl
, ")");
1138 /* After picking off the function args, we expect to either find the
1139 function return type (preceded by an '_') or the end of the
1141 if (!demangle_args (&decl
, type
, work
)
1142 || (**type
!= '_' && **type
!= '\0'))
1146 if (success
&& (**type
== '_'))
1158 member
= **type
== 'M';
1160 if (!isdigit (**type
))
1172 while (isdigit (**type
));
1173 if (strlen (*type
) < n
)
1178 string_append (&decl
, ")");
1179 string_prepend (&decl
, "::");
1180 string_prependn (&decl
, *type
, n
);
1181 string_prepend (&decl
, "(");
1195 if (*(*type
)++ != 'F')
1201 if ((member
&& !demangle_args (&decl
, type
, work
))
1208 if (! PRINT_ANSI_QUALIFIERS
)
1214 APPEND_BLANK (&decl
);
1215 string_append (&decl
, "const");
1219 APPEND_BLANK (&decl
);
1220 string_append (&decl
, "volatile");
1226 if ((*type
)[1] == 'P')
1229 if (PRINT_ANSI_QUALIFIERS
)
1231 if (!STRING_EMPTY (&decl
))
1233 string_prepend (&decl
, " ");
1235 string_prepend (&decl
, "const");
1247 success
= demangle_fund_type (type
, result
, work
);
1251 if (!STRING_EMPTY (&decl
))
1253 string_append (result
, " ");
1254 string_appends (result
, &decl
);
1259 string_delete (result
);
1261 string_delete (&decl
);
1265 /* Given a pointer to a type string that represents a fundamental type
1266 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
1267 string in which the demangled output is being built in RESULT, and
1268 the WORK structure, decode the types and add them to the result.
1273 "Sl" => "signed long"
1274 "CUs" => "const unsigned short"
1279 demangle_fund_type (type
, result
, work
)
1282 struct work_stuff
*work
;
1288 /* First pick off any type qualifiers. There can be more than one. */
1296 if (PRINT_ANSI_QUALIFIERS
)
1298 APPEND_BLANK (result
);
1299 string_append (result
, "const");
1304 APPEND_BLANK (result
);
1305 string_append (result
, "unsigned");
1307 case 'S': /* signed char only */
1309 APPEND_BLANK (result
);
1310 string_append (result
, "signed");
1314 if (PRINT_ANSI_QUALIFIERS
)
1316 APPEND_BLANK (result
);
1317 string_append (result
, "volatile");
1326 /* Now pick off the fundamental type. There can be only one. */
1335 APPEND_BLANK (result
);
1336 string_append (result
, "void");
1340 APPEND_BLANK (result
);
1341 string_append (result
, "long long");
1345 APPEND_BLANK (result
);
1346 string_append (result
, "long");
1350 APPEND_BLANK (result
);
1351 string_append (result
, "int");
1355 APPEND_BLANK (result
);
1356 string_append (result
, "short");
1360 APPEND_BLANK (result
);
1361 string_append (result
, "char");
1365 APPEND_BLANK (result
);
1366 string_append (result
, "long double");
1370 APPEND_BLANK (result
);
1371 string_append (result
, "double");
1375 APPEND_BLANK (result
);
1376 string_append (result
, "float");
1380 if (!isdigit (**type
))
1386 /* An explicit type, such as "6mytype" or "7integer" */
1404 while (isdigit (**type
));
1405 if (strlen (*type
) < n
)
1410 APPEND_BLANK (result
);
1411 string_appendn (result
, *type
, n
);
1422 /* `result' will be initialized in do_type; it will be freed on failure */
1425 do_arg (type
, result
, work
)
1428 struct work_stuff
*work
;
1430 const char *start
= *type
;
1432 if (!do_type (type
, result
, work
))
1438 remember_type (start
, *type
- start
, work
);
1444 remember_type (start
, len
, work
)
1447 struct work_stuff
*work
;
1451 if (work
-> ntypes
>= work
-> typevec_size
)
1453 if (work
-> typevec_size
== 0)
1455 work
-> typevec_size
= 3;
1457 (char **) xmalloc (sizeof (char *) * work
-> typevec_size
);
1461 work
-> typevec_size
*= 2;
1463 (char **) xrealloc ((char *)work
-> typevec
,
1464 sizeof (char *) * work
-> typevec_size
);
1467 tem
= (char *) xmalloc (len
+ 1);
1468 memcpy (tem
, start
, len
);
1470 work
-> typevec
[work
-> ntypes
++] = tem
;
1473 /* Process the argument list part of the signature, after any class spec
1474 has been consumed, as well as the first 'F' character (if any). For
1477 "__als__3fooRT0" => process "RT0"
1478 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
1480 DECLP must be already initialised, usually non-empty. It won't be freed
1484 demangle_args (declp
, type
, work
)
1487 struct work_stuff
*work
;
1496 if (PRINT_ARG_TYPES
)
1498 string_append (declp
, "(");
1501 string_append (declp
, "void");
1505 while (**type
!= '_' && **type
!= '\0' && **type
!= 'e')
1507 if ((**type
== 'N') || (**type
== 'T'))
1509 temptype
= *(*type
)++;
1511 if (temptype
== 'N')
1513 if (!get_count (type
, &r
))
1522 if (!get_count (type
, &t
))
1526 #ifdef ARM_DEMANGLING
1529 if (t
>= work
-> ntypes
)
1535 tem
= work
-> typevec
[t
];
1536 if (need_comma
&& PRINT_ARG_TYPES
)
1538 string_append (declp
, ", ");
1540 if (!do_arg (&tem
, &arg
, work
))
1544 if (PRINT_ARG_TYPES
)
1546 string_appends (declp
, &arg
);
1548 string_delete (&arg
);
1554 if (need_comma
& PRINT_ARG_TYPES
)
1556 string_append (declp
, ", ");
1558 if (!do_arg (type
, &arg
, work
))
1562 if (PRINT_ARG_TYPES
)
1564 string_appends (declp
, &arg
);
1566 string_delete (&arg
);
1574 if (PRINT_ARG_TYPES
)
1578 string_append (declp
, ",");
1580 string_append (declp
, "...");
1584 if (PRINT_ARG_TYPES
)
1586 string_append (declp
, ")");
1592 demangle_function_name (declp
, mangled
, work
, scan
)
1594 const char **mangled
;
1595 struct work_stuff
*work
;
1603 string_appendn (declp
, (*mangled
), scan
- (*mangled
));
1604 string_need (declp
, 1);
1605 *(declp
-> p
) = '\0';
1607 /* Consume the function name, including the "__" separating the name
1608 from the signature. We are guaranteed that SCAN points to the
1611 (*mangled
) = scan
+ 2;
1613 #ifdef ARM_DEMANGLING
1615 /* See if we have an ARM style constructor or destructor operator.
1616 If so, then just record it, clear the decl, and return.
1617 We can't build the actual constructor/destructor decl until later,
1618 when we recover the class name from the signature. */
1620 if (strcmp (declp
-> b
, "__ct") == 0)
1622 work
-> constructor
= 1;
1623 string_clear (declp
);
1626 else if (strcmp (declp
-> b
, "__dt") == 0)
1628 work
-> destructor
= 1;
1629 string_clear (declp
);
1635 if (declp
->p
- declp
->b
>= 3
1636 && declp
->b
[0] == 'o'
1637 && declp
->b
[1] == 'p'
1638 && declp
->b
[2] == CPLUS_MARKER
)
1640 /* see if it's an assignment expression */
1641 if (declp
->p
- declp
->b
>= 10 /* op$assign_ */
1642 && memcmp (declp
->b
+ 3, "assign_", 7) == 0)
1644 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
1646 len
= declp
->p
- declp
->b
- 10;
1647 if (strlen (optable
[i
].in
) == len
1648 && memcmp (optable
[i
].in
, declp
->b
+ 10, len
) == 0)
1650 string_clear (declp
);
1651 string_append (declp
, "operator");
1652 string_append (declp
, optable
[i
].out
);
1653 string_append (declp
, "=");
1660 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
1662 int len
= declp
->p
- declp
->b
- 3;
1663 if (strlen (optable
[i
].in
) == len
1664 && memcmp (optable
[i
].in
, declp
->b
+ 3, len
) == 0)
1666 string_clear (declp
);
1667 string_append (declp
, "operator");
1668 string_append (declp
, optable
[i
].out
);
1674 else if (declp
->p
- declp
->b
>= 5 && memcmp (declp
->b
, "type$", 5) == 0)
1676 /* type conversion operator */
1678 if (do_type (&tem
, &type
, work
))
1680 string_clear (declp
);
1681 string_append (declp
, "operator ");
1682 string_appends (declp
, &type
);
1683 string_delete (&type
);
1686 else if (declp
->b
[2] == 'o' && declp
->b
[3] == 'p')
1689 /* type conversion operator. */
1691 if (do_type (&tem
, &type
, work
))
1693 string_clear (declp
);
1694 string_append (declp
, "operator ");
1695 string_appends (declp
, &type
);
1696 string_delete (&type
);
1699 else if (declp
->b
[0] == '_' && declp
->b
[1] == '_'
1700 && declp
->b
[2] >= 'a' && declp
->b
[2] <= 'z'
1701 && declp
->b
[3] >= 'a' && declp
->b
[3] <= 'z')
1703 if (declp
->b
[4] == '\0')
1706 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
1708 if (strlen (optable
[i
].in
) == 2
1709 && memcmp (optable
[i
].in
, declp
->b
+ 2, 2) == 0)
1711 string_clear (declp
);
1712 string_append (declp
, "operator");
1713 string_append (declp
, optable
[i
].out
);
1720 if (declp
->b
[2] == 'a' && declp
->b
[5] == '\0')
1723 for (i
= 0; i
< sizeof (optable
) / sizeof (optable
[0]); i
++)
1725 if (strlen (optable
[i
].in
) == 3
1726 && memcmp (optable
[i
].in
, declp
->b
+ 2, 3) == 0)
1728 string_clear (declp
);
1729 string_append (declp
, "operator");
1730 string_append (declp
, optable
[i
].out
);
1739 /* a mini string-handling package */
1754 s
->p
= s
->b
= (char *) xmalloc (n
);
1757 else if (s
->e
- s
->p
< n
)
1762 s
->b
= (char *) xrealloc (s
->b
, n
);
1775 s
->b
= s
->e
= s
->p
= NULL
;
1783 s
->b
= s
->p
= s
->e
= NULL
;
1797 return (s
->b
== s
->p
);
1801 string_append (p
, s
)
1806 if (s
== NULL
|| *s
== '\0')
1810 memcpy (p
->p
, s
, n
);
1815 string_appends (p
, s
)
1824 memcpy (p
->p
, s
->b
, n
);
1830 string_appendn (p
, s
, n
)
1838 memcpy (p
->p
, s
, n
);
1844 string_prepend (p
, s
)
1848 if (s
!= NULL
&& *s
!= '\0')
1850 string_prependn (p
, s
, strlen (s
));
1856 string_prepends (p
, s
)
1861 string_prependn (p
, s
->b
, s
->p
- s
->b
);
1867 string_prependn (p
, s
, n
)
1877 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
1881 memcpy (p
->b
, s
, n
);
1886 /* To generate a standalone demangler program for testing purposes, just
1887 compile and link this file with -DMAIN. When run, it demangles each
1888 command line arg, or each stdin string, and prints the result on stdout. */
1893 demangle_it (mangled_name
)
1898 result
= cplus_demangle (mangled_name
, DMGL_PARAMS
| DMGL_ANSI
);
1901 printf ("%s\n", mangled_name
);
1905 printf ("%s\n", result
);
1916 if ((newmem
= malloc ((int) size
)) == NULL
)
1918 fprintf (stderr
, "\nCan't allocate %u bytes\n", size
);
1925 xrealloc (oldmem
, size
)
1931 if ((newmem
= realloc ((char *) oldmem
, (int) size
)) == NULL
)
1933 fprintf (stderr
, "\nCan't reallocate %u bytes\n", size
);
1943 char mangled_name
[128];
1952 demangle_it (*argv
);
1957 while (gets (mangled_name
))
1959 demangle_it (mangled_name
);
This page took 0.069214 seconds and 4 git commands to generate.