Copyright (C) 1989 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 1, 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). */
/* This file exports one function
char *cplus_demangle (const char *name, int mode)
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
If MODE > 0, then ANSI qualifiers such as `const' and `void' are output.
If MODE >= 0, parameters are emitted; otherwise not.
cplus_demangle ("foo__1Ai", 0) => "A::foo(int)"
cplus_demangle ("foo__1Ai", 1) => "A::foo(int)"
cplus_demangle ("foo__1Ai", -1) => "A::foo"
cplus_demangle ("foo__1Afe", 0) => "A::foo(float,...)"
cplus_demangle ("foo__1Afe", 1) => "A::foo(float,...)"
cplus_demangle ("foo__1Afe", -1) => "A::foo"
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))
extern char *cplus_demangle (const char *type
, int mode
);
extern char *cplus_demangle ();
extern char *xmalloc (int);
extern char *xrealloc (char *, int);
extern char *xrealloc ();
static char **typevec
= 0;
static int typevec_size
= 0;
"convert", "+", /* unary + */
"negate", "-", /* unary - */
"addr", "&", /* unary & */
"nop", "", /* 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
, int arg_mode
);
static int do_type (const char **type
, string
*result
, int arg_mode
);
static int do_arg (const char **type
, string
*result
, int arg_mode
);
static void munge_function_name (string
*name
, int arg_mode
);
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 ();
cplus_demangle (type
, arg_mode
)
# define print_ansi_qualifiers (arg_mode > 0)
# define print_arg_types (arg_mode >= 0)
if (type
== NULL
|| *type
== '\0')
while (*p
!= '\0' && !(*p
== '_' && p
[1] == '_'))
if (type
[0] == '_' && type
[1] == '$' && type
[2] == '_')
int n
= (strlen (type
) - 3)*2 + 3 + 2 + 1;
char *tem
= (char *) xmalloc (n
);
if (*type
!= '_' && (p
= strchr (type
, '$')) != NULL
)
int n
= strlen (type
) + 2;
char *tem
= (char *) xmalloc (n
);
memcpy (tem
, type
, p
- type
);
strcpy (tem
+ (p
- type
), "::");
strcpy (tem
+ (p
- type
) + 2, p
+ 1);
/* virtual table "_vt$" */
if (type
[0] == '_' && type
[1] == 'v' && type
[2] == 't' && type
[3] == '$')
int n
= strlen (type
+ 4) + 14 + 1;
char *tem
= (char *) xmalloc (n
);
strcat (tem
, " virtual table");
string_appendn (&decl
, type
, p
- type
);
munge_function_name (&decl
, arg_mode
);
/* a const member function */
string_appendn (&decl
, p
, n
);
string_append (&decl
, "::");
string_appendn (&decl
, p
, n
);
string_prepend (&decl
, "::");
string_prependn (&decl
, p
, n
);
remember_type (premangle
, p
- premangle
);
success
= do_args (&p
, &decl
, arg_mode
);
if (const_flag
&& print_arg_types
)
string_append (&decl
, " const");
success
= do_args (&p
, &decl
, arg_mode
);
for (i
= 0; i
< ntypes
; i
++)
string_appendn (&decl
, "", 1);
/* see flush_repeats in cplus-method.c */
/* result will be initialised here; it will be freed on failure */
do_type (type
, result
, arg_mode
)
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
, arg_mode
) || **type
!= '_')
while (isdigit (**type
));
string_append (&decl
, ")");
string_prepend (&decl
, "::");
string_prependn (&decl
, *type
, n
);
string_prepend (&decl
, "(");
if ((member
&& !do_args (type
, &decl
, arg_mode
)) || **type
!= '_')
if (! print_ansi_qualifiers
)
string_append (&decl
, " ");
string_append (&decl
, "const");
string_append (&decl
, " ");
string_append (&decl
, "volatile");
if (print_ansi_qualifiers
)
if (!string_empty (&decl
))
string_prepend (&decl
, " ");
string_prepend (&decl
, "const");
if (print_ansi_qualifiers
)
string_append (result
, " ");
string_append (result
, "const");
string_append (result
, " ");
string_append (result
, "unsigned");
if (print_ansi_qualifiers
)
string_append (result
, " ");
string_append (result
, "volatile");
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
, "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
);
if (!string_empty (&decl
))
string_append (result
, " ");
string_appends (result
, &decl
);
/* `result' will be initialised in do_type; it will be freed on failure */
do_arg (type
, result
, arg_mode
)
const char *start
= *type
;
if (!do_type (type
, result
, arg_mode
))
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 */
do_args (type
, decl
, arg_mode
)
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
];
if (need_comma
&& print_arg_types
)
string_append (decl
, ", ");
if (!do_arg (&tem
, &arg
, arg_mode
))
string_appends (decl
, &arg
);
if (need_comma
& print_arg_types
)
string_append (decl
, ", ");
if (!do_arg (type
, &arg
, arg_mode
))
string_appends (decl
, &arg
);
string_append (decl
, ",");
string_append (decl
, "...");
string_append (decl
, ")");
munge_function_name (name
, arg_mode
)
if (!string_empty (name
) && name
->p
- name
->b
>= 3
&& name
->b
[0] == 'o' && name
->b
[1] == 'p' && name
->b
[2] == '$')
/* 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 (!string_empty (name
) && 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
, arg_mode
))
string_append (name
, "operator ");
string_appends (name
, &type
);
/* 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
--)