Copyright (C) 1989, 1992 Free Software Foundation, Inc.
written by James Clark (jjc@jclark.uucp)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This is for g++ 1.36.1 (November 6 version). It will probably
require changes for any other version.
Modified for g++ 1.36.2 (November 18 version).
Modified for g++ 1.90.06 (December 31 version).
Modified for g++ 1.95.03 (November 13 version). */
/* This file exports one function
char *cplus_demangle (const char *name)
If NAME is a mangled function name produced by GNU C++, then
a pointer to a malloced string giving a C++ representation
of the name will be returned; otherwise NULL will be returned.
It is the caller's responsibility to free the string which
cplus_demangle ("_foo__1Ai")
This file imports xmalloc and xrealloc, which are like malloc and
realloc except that they generate a fatal error if there is no
/* #define nounderscore 1 /* define this is names don't start with _ */
#define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
#define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
/* This is '$' on systems where the assembler can deal with that.
Where the assembler can't, it's '.' (but on many systems '.' is
used for other things). */
#if !defined (CPLUS_MARKER)
extern char *cplus_demangle (const char *type
);
extern char *cplus_demangle ();
extern char *xmalloc (int);
extern char *xrealloc (char *, int);
extern void free (char *);
extern char *xrealloc ();
static char **typevec
= 0;
static int typevec_size
= 0;
"nw", " new", /* new (1.92, ansi) */
"dl", " delete", /* new (1.92, ansi) */
"new", " new", /* old (1.91) */
"delete", " delete", /* old (1.91) */
"ne", "!=", /* old, ansi */
"eq", "==", /* old, ansi */
"ge", ">=", /* old, ansi */
"gt", ">", /* old, ansi */
"le", "<=", /* old, ansi */
"lt", "<", /* old, ansi */
"convert", "+", /* old (unary +) */
"negate", "-", /* old (unary -) */
"trunc_mod", "%", /* old */
"trunc_div", "/", /* old */
"truth_andif", "&&", /* old */
"truth_orif", "||", /* old */
"truth_not", "!", /* old */
"postincrement", "++", /* old */
"postdecrement", "--", /* old */
"bit_ior", "|", /* old */
"bit_xor", "^", /* old */
"bit_and", "&", /* old */
"bit_not", "~", /* old */
"alshift", "<<", /* old */
"arshift", ">>", /* old */
"component", "->", /* old */
"indirect", "*", /* old */
"method_call", "->()", /* old */
"addr", "&", /* old (unary &) */
"compound", ",", /* old */
"nop", "", /* old (for operator=) */
/* Beware: these aren't '\0' terminated. */
char *b
; /* pointer to start of string */
char *p
; /* pointer after last character */
char *e
; /* pointer after end of allocated space */
static void string_need (string
*s
, int n
);
static void string_delete (string
*s
);
static void string_init (string
*s
);
static void string_clear (string
*s
);
static int string_empty (string
*s
);
static void string_append (string
*p
, const char *s
);
static void string_appends (string
*p
, string
*s
);
static void string_appendn (string
*p
, const char *s
, int n
);
static void string_prepend (string
*p
, const char *s
);
static void string_prepends (string
*p
, string
*s
);
static void string_prependn (string
*p
, const char *s
, int n
);
static int get_count (const char **type
, int *count
);
static int do_args (const char **type
, string
*decl
);
static int do_type (const char **type
, string
*result
);
static int do_arg (const char **type
, string
*result
);
static int do_args (const char **type
, string
*decl
);
static void munge_function_name (string
*name
);
static void remember_type (const char *type
, int len
);
static void string_need ();
static void string_delete ();
static void string_init ();
static void string_clear ();
static int string_empty ();
static void string_append ();
static void string_appends ();
static void string_appendn ();
static void string_prepend ();
static void string_prepends ();
static void string_prependn ();
static void munge_function_name ();
static void remember_type ();
get_simple_count (type
, res
)
while (isdigit (**type
));
if (type
== NULL
|| *type
== '\0')
while (*p
!= '\0' && !(*p
== '_' && p
[1] == '_'))
if (type
[0] == '_' && type
[1] == CPLUS_MARKER
&& type
[2] == '_')
else if (*type
!= '_' && (index (type
, CPLUS_MARKER
) != NULL
))
/* virtual table "_vt$" */
else if (type
[0] == '_' && type
[1] == 'v' && type
[2] == 't' && type
[3] == CPLUS_MARKER
)
int n
= strlen (type
+ 4) + 14 + 1;
char *tem
= (char *) xmalloc (n
);
strcat (tem
, " virtual table");
if (!isdigit (p
[0]) && ('t' != p
[0]))
if (!isdigit (p
[3])&& ('t' != p
[3]))
if (!isdigit (p
[2]) && ('t' != p
[2]))
while (*p
!= '\0' && !(*p
== '_' && p
[1] == '_'))
string_appendn (&decl
, type
, p
- type
);
string_appendn (&decl
, "", 1);
munge_function_name (&decl
);
string_appendn (&decl
, type
, p
- type
);
munge_function_name (&decl
);
/* a const member function */
if (constructor
|| destructor
)
string_appendn (&decl
, p
, n
);
string_append (&decl
, "::");
string_append(&decl
, "~");
string_appendn (&decl
, p
, n
);
string_prepend (&decl
, "::");
string_prependn (&decl
, p
, n
);
remember_type (premangle
, p
- premangle
);
string_append(&decl
, p
+1);
success
= do_args (&p
, &decl
);
string_append (&decl
, " const");
success
= do_args (&p
, &decl
);
if (!get_simple_count (&p
, &r
))
string_appendn (&tname
, p
, r
);
string_appendn (&trawname
, p
, r
);
string_appendn (&trawname
, "", 1);
string_append (&tname
, "<");
/* get size of template parameter list */
string_append (&tname
, ", ");
/* Z for type parameters */
success
= do_type (&p
, &temp
);
string_appendn (&temp
, "", 1);
string_append (&tname
, temp
.b
);
/* otherwise, value parameter */
success
= do_type (&p
, &temp
);
string_appendn (&temp
, "", 1);
string_append (&tname
, temp
.b
);
string_append (&tname
, "=");
case 'M': /* member function */
case 'Q': /* repetition of following */
case 'T': /* remembered type */
case 'x': /* long long */
case 'r': /* long double */
string_appendn (&tname
, "-", 1);
string_appendn (&tname
, p
, 1);
string_appendn (&tname
, "-", 1);
string_appendn (&tname
, p
, 1);
if (*p
== '.') /* fraction */
string_appendn (&tname
, ".", 1);
string_appendn (&tname
, p
, 1);
if (*p
== 'e') /* exponent */
string_appendn (&tname
, "e", 1);
string_appendn (&tname
, p
, 1);
if (!get_count (&p
, &symbol_len
))
string_appendn (&tname
, p
, symbol_len
);
string_append (&tname
, ">::");
string_append(&tname
, "~");
if (constructor
|| destructor
) {
string_appendn (&trawname
, "", 1);
string_append (&tname
, trawname
.b
);
string_delete(&trawname
);
string_appendn (&tname
, "", 1);
string_prepend (&decl
, tname
.b
);
string_append (&decl
, p
+1);
success
= do_args (&p
, &decl
);
for (i
= 0; i
< ntypes
; i
++)
string_appendn (&decl
, "", 1);
/* see flush_repeats in cp-method.c */
/* result will be initialised here; it will be freed on failure */
const char *remembered_type
;
string_prepend (&decl
, "*");
string_prepend (&decl
, "&");
if (!get_count (type
, &n
) || n
>= ntypes
)
remembered_type
= typevec
[n
];
if (!string_empty (&decl
) && decl
.b
[0] == '*')
string_prepend (&decl
, "(");
string_append (&decl
, ")");
if (!do_args (type
, &decl
) || **type
!= '_')
while (isdigit (**type
));
string_append (&decl
, ")");
string_prepend (&decl
, "::");
string_prependn (&decl
, *type
, n
);
string_prepend (&decl
, "(");
if ((member
&& !do_args (type
, &decl
)) || **type
!= '_')
string_append (&decl
, " ");
string_append (&decl
, "const");
string_append (&decl
, " ");
string_append (&decl
, "volatile");
if (!string_empty (&decl
))
string_prepend (&decl
, " ");
string_prepend (&decl
, "const");
success
= do_cuv_prefix (type
, result
, &non_empty
);
success
= do_builtin_type(type
, result
, &non_empty
);
if (!string_empty (&decl
))
string_append (result
, " ");
string_appends (result
, &decl
);
do_cuv_prefix (type
, result
, non_empty
)
string_append (result
, " ");
string_append (result
, "const");
string_append (result
, " ");
string_append (result
, "unsigned");
string_append (result
, " ");
string_append (result
, "volatile");
do_builtin_type (type
, result
, non_empty
)
string_append (result
, " ");
string_append (result
, "void");
string_append (result
, " ");
string_append (result
, "long long");
string_append (result
, " ");
string_append (result
, "long");
string_append (result
, " ");
string_append (result
, "int");
string_append (result
, " ");
string_append (result
, "short");
string_append (result
, " ");
string_append (result
, "char");
string_append (result
, " ");
string_append (result
, "wchar_t");
string_append (result
, " ");
string_append (result
, "long double");
string_append (result
, " ");
string_append (result
, "double");
string_append (result
, " ");
string_append (result
, "float");
while (isdigit (**type
));
string_append (result
, " ");
string_appendn (result
, *type
, n
);
/* `result' will be initialised in do_type; it will be freed on failure */
const char *start
= *type
;
if (!do_type (type
, result
))
remember_type (start
, *type
- start
);
remember_type (start
, len
)
if (ntypes
>= typevec_size
)
typevec
= (char **) xmalloc (sizeof (char*)*typevec_size
);
typevec
= (char **) xrealloc ((char *)typevec
, sizeof (char*)*typevec_size
);
tem
= (char *) xmalloc (len
+ 1);
memcpy (tem
, start
, len
);
/* `decl' must be already initialised, usually non-empty;
it won't be freed on failure */
string_append (decl
, "(");
while (**type
!= '_' && **type
!= '\0' && **type
!= 'e' && **type
!= 'v')
if (!get_count (type
, &r
) || !get_count (type
, &t
) || t
>= ntypes
)
const char *tem
= typevec
[t
];
string_append (decl
, ", ");
if (!do_arg (&tem
, &arg
))
string_appends (decl
, &arg
);
string_append (decl
, ", ");
if (!do_arg (type
, &arg
))
string_appends (decl
, &arg
);
string_append (decl
, ",");
string_append (decl
, "...");
string_append (decl
, ")");
munge_function_name (name
)
if (name
->p
- name
->b
>= 3
&& name
->b
[0] == 'o' && name
->b
[1] == 'p' && name
->b
[2] == CPLUS_MARKER
)
/* see if it's an assignment expression */
if (name
->p
- name
->b
>= 10 /* op$assign_ */
&& memcmp (name
->b
+ 3, "assign_", 7) == 0)
for (i
= 0; i
< sizeof (optable
)/sizeof (optable
[0]); i
++)
int len
= name
->p
- name
->b
- 10;
if (strlen (optable
[i
].in
) == len
&& memcmp (optable
[i
].in
, name
->b
+ 10, len
) == 0)
string_append (name
, "operator");
string_append (name
, optable
[i
].out
);
string_append (name
, "=");
for (i
= 0; i
< sizeof (optable
)/sizeof (optable
[0]); i
++)
int len
= name
->p
- name
->b
- 3;
if (strlen (optable
[i
].in
) == len
&& memcmp (optable
[i
].in
, name
->b
+ 3, len
) == 0)
string_append (name
, "operator");
string_append (name
, optable
[i
].out
);
else if (name
->p
- name
->b
>= 5 && memcmp (name
->b
, "type$", 5) == 0)
/* type conversion operator */
const char *tem
= name
->b
+ 5;
if (do_type (&tem
, &type
))
string_append (name
, "operator ");
string_appends (name
, &type
);
else if (name
->b
[2] == 'o' && name
->b
[3] == 'p')
/* type conversion operator. */
const char *tem
= name
->b
+ 4;
if (do_type (&tem
, &type
))
string_append (name
, "operator ");
string_appends (name
, &type
);
else if (name
->b
[2] >= 'a' && name
->b
[2] <= 'z'
&& name
->b
[3] >= 'a' && name
->b
[3] <= 'z')
for (i
= 0; i
< sizeof (optable
)/sizeof (optable
[0]); i
++)
if (strlen (optable
[i
].in
) == 2
&& memcmp (optable
[i
].in
, name
->b
+ 2, 2) == 0)
string_append (name
, "operator");
string_append (name
, optable
[i
].out
);
if (name
->b
[2] != 'a' || name
->b
[5] != '\0')
for (i
= 0; i
< sizeof (optable
)/sizeof (optable
[0]); i
++)
if (strlen (optable
[i
].in
) == 3
&& memcmp (optable
[i
].in
, name
->b
+ 2, 3) == 0)
string_append (name
, "operator");
string_append (name
, optable
[i
].out
);
/* a mini string-handling package */
s
->p
= s
->b
= (char *) xmalloc (n
);
else if (s
->e
- s
->p
< n
)
s
->b
= (char *) xrealloc (s
->b
, n
);
s
->b
= s
->e
= s
->p
= NULL
;
s
->b
= s
->p
= s
->e
= NULL
;
if (s
== NULL
|| *s
== '\0')
if (s
== NULL
|| *s
== '\0')
string_prependn (p
, s
, strlen (s
));
string_prependn (p
, s
->b
, s
->p
- s
->b
);
string_prependn (p
, s
, n
)
for (q
= p
->p
- 1; q
>= p
->b
; q
--)