coff_symconst_h = $(INCLUDE_DIR)/coff/symconst.h
coff_ecoff_h = $(INCLUDE_DIR)/coff/ecoff.h
coff_internal_h = $(INCLUDE_DIR)/coff/internal.h
+cp_demangle_h = $(INCLUDE_DIR)/cp-demangle.h
dis_asm_h = $(INCLUDE_DIR)/dis-asm.h $(bfd_h)
elf_reloc_macros_h = $(INCLUDE_DIR)/elf/reloc-macros.h
elf_sh_h = $(INCLUDE_DIR)/elf/sh.h
complaints_h = complaints.h
completer_h = completer.h
cp_abi_h = cp-abi.h
-cp_names_h = cp-names.h
cp_support_h = cp-support.h $(symtab_h)
dcache_h = dcache.h
defs_h = defs.h $(config_h) $(ansidecl_h) $(gdb_locale_h) $(gdb_signals_h) \
-rm c-exp.tmp
mv c-exp.new ./c-exp.tab.c
-cp-names.tab.o: cp-names.tab.c $(safe_ctype_h) $(cp_names_h) \
- $(srcdir)/../include/cp-demangle.h
+cp-names.tab.o: cp-names.tab.c $(safe_ctype_h) $(cp_demangle_h)
-cp-names-main.tab.o: cp-names.tab.c $(safe_ctype_h) $(cp_names_h) \
- $(srcdir)/../include/cp-demangle.h
+cp-names-main.tab.o: cp-names.tab.c $(safe_ctype_h) $(cp_demangle_h)
$(CC) -c $(INTERNAL_CFLAGS) -DTEST_CPNAMES \
-o cp-names-main.tab.o cp-names.tab.c
test-cpnames: cp-names-main.tab.o $(LIBIBERTY)
$(gdbtypes_h) $(dictionary_h) $(command_h)
cp-support.o: cp-support.c $(defs_h) $(cp_support_h) $(gdb_string_h) \
$(demangle_h) $(gdb_assert_h) $(gdbcmd_h) $(dictionary_h) \
- $(objfiles_h) $(frame_h) $(symtab_h) $(block_h) $(complaints_h)
+ $(objfiles_h) $(frame_h) $(symtab_h) $(block_h) $(complaints_h) \
+ $(cp_demangle_h)
cpu32bug-rom.o: cpu32bug-rom.c $(defs_h) $(gdbcore_h) $(target_h) \
$(monitor_h) $(serial_h) $(regcache_h) $(m68k_tdep_h)
cp-valprint.o: cp-valprint.c $(defs_h) $(gdb_obstack_h) $(symtab_h) \
#define IN_GDB
#include "cp-demangle.h"
-#include "cp-names.h"
-
static const char *lexptr, *prev_lexptr;
static struct d_comp *d_qualify (struct d_comp *, int, int);
return p;
}
-static char *
+char *
cp_comp_to_string (struct d_comp *result, int estimated_len)
{
char *str, *prefix = NULL, *buf;
return (buf);
}
-/* Return the canonicalized form of STRING, or NULL if STRING can not be
- parsed. */
+/* Convert a demangled name to a d_comp tree. *DI_P is set to the
+ struct d_info that should be freed when finished with the tree. */
-char *
-cp_canonicalize_string (const char *string)
+struct d_comp *
+demangled_name_to_comp (const char *demangled_name, struct d_info **di_p)
{
- int len = strlen (string);
- char *ret;
+ int len = strlen (demangled_name);
len = len + len / 8;
+ lexptr = demangled_name;
- lexptr = string;
di = cp_v3_d_init_info_alloc (NULL, DMGL_PARAMS | DMGL_ANSI, len);
+
if (yyparse () || result == NULL)
- return NULL;
+ {
+ cp_v3_d_free_info (di);
+ return NULL;
+ }
- ret = cp_comp_to_string (result, len);
+ *di_p = di;
+ return result;
+}
+
+/* Convert a mangled name to a d_comp tree. *DI_P is set to the
+ struct d_info that should be freed when finished with the tree.
+ DEMANGLED_P is set to the char * that should be freed when finished
+ with the tree. OPTIONS will be passed to the demangler.
+
+ This could be done much more efficiently for v3 mangled names by exposing
+ d_demangle from the demangler. */
+
+struct d_comp *
+mangled_name_to_comp (const char *mangled_name, int options,
+ struct d_info **di_p, char **demangled_p)
+{
+ char *demangled_name = cplus_demangle (mangled_name, options);
+ int len;
+ struct d_comp *ret;
- cp_v3_d_free_info (di);
+ if (demangled_name == NULL)
+ return NULL;
+
+ ret = demangled_name_to_comp (demangled_name, di_p);
+
+ if (ret == NULL)
+ {
+ free (demangled_name);
+ return NULL;
+ }
+ *demangled_p = demangled_name;
return ret;
}
/* Helper routines for C++ support in GDB.
- Copyright 2002, 2003 Free Software Foundation, Inc.
+ Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by MontaVista Software.
#include "complaints.h"
#include "gdbtypes.h"
+#define IN_GDB
+#include "cp-demangle.h"
+
/* Functions related to demangled name parsing. */
static const char *find_last_component (const char *name);
static void maint_cplus_command (char *arg, int from_tty);
static void first_component_command (char *arg, int from_tty);
-/* Here are some random pieces of trivia to keep in mind while trying
- to take apart demangled names:
-
- - Names can contain function arguments or templates, so the process
- has to be, to some extent recursive: maybe keep track of your
- depth based on encountering <> and ().
-
- - Parentheses don't just have to happen at the end of a name: they
- can occur even if the name in question isn't a function, because
- a template argument might be a type that's a function.
-
- - Conversely, even if you're trying to deal with a function, its
- demangled name might not end with ')': it could be a const or
- volatile class method, in which case it ends with "const" or
- "volatile".
-
- - Parentheses are also used in anonymous namespaces: a variable
- 'foo' in an anonymous namespace gets demangled as "(anonymous
- namespace)::foo".
-
- - And operator names can contain parentheses or angle brackets. */
-
-/* FIXME: carlton/2003-03-13: We have several functions here with
- overlapping functionality; can we combine them? Also, do they
- handle all the above considerations correctly? */
-
-/* Find the last component of the demangled C++ name NAME. NAME
- must be a method name including arguments, in order to correctly
- locate the last component.
+/* Return the canonicalized form of STRING, or NULL if STRING can not be
+ parsed. */
- This function return a pointer to the first colon before the
- last component, or NULL if the name had only one component. */
+/* FIXME: Should we also return NULL for things that trivially do not require
+ any change? i.e. alphanumeric strings. */
-static const char *
-find_last_component (const char *name)
+char *
+cp_canonicalize_string (const char *string)
{
- const char *p;
- int depth;
+ struct d_info *di;
+ struct d_comp *ret_comp;
+ char *ret;
+ int len = strlen (string);
- /* Functions can have local classes, so we need to find the
- beginning of the last argument list, not the end of the first
- one. */
- p = name + strlen (name) - 1;
- while (p > name && *p != ')')
- p--;
+ len = len + len / 8;
- if (p == name)
+ ret_comp = demangled_name_to_comp (string, &di);
+ if (ret_comp == NULL)
return NULL;
- /* P now points at the `)' at the end of the argument list. Walk
- back to the beginning. */
- p--;
- depth = 1;
- while (p > name && depth > 0)
- {
- if (*p == '<' || *p == '(')
- depth--;
- else if (*p == '>' || *p == ')')
- depth++;
- p--;
- }
-
- if (p == name)
- return NULL;
+ ret = cp_comp_to_string (ret_comp, len);
- while (p > name && *p != ':')
- p--;
+ cp_v3_d_free_info (di);
- if (p == name || p == name + 1 || p[-1] != ':')
- return NULL;
-
- return p - 1;
+ return ret;
}
/* Return the name of the class containing method PHYSNAME. */
char *
class_name_from_physname (const char *physname)
{
- char *ret = NULL;
- const char *end;
- int depth = 0;
- char *demangled_name = cplus_demangle (physname, DMGL_ANSI | DMGL_PARAMS);
+ struct d_info *di;
+ char *demangled_name, *ret;
+ struct d_comp *ret_comp, *prev_comp;
+ int done;
- if (demangled_name == NULL)
+ ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &di, &demangled_name);
+ if (ret_comp == NULL)
return NULL;
- end = find_last_component (demangled_name);
- if (end != NULL)
+ done = 0;
+ prev_comp = NULL;
+ while (!done)
+ switch (ret_comp->type)
+ {
+ case D_COMP_TYPED_NAME:
+ prev_comp = NULL;
+ ret_comp = d_right (ret_comp);
+ break;
+ case D_COMP_QUAL_NAME:
+ case D_COMP_LOCAL_NAME:
+ prev_comp = ret_comp;
+ ret_comp = d_right (ret_comp);
+ break;
+ case D_COMP_CONST:
+ case D_COMP_RESTRICT:
+ case D_COMP_VOLATILE:
+ case D_COMP_CONST_THIS:
+ case D_COMP_RESTRICT_THIS:
+ case D_COMP_VOLATILE_THIS:
+ case D_COMP_VENDOR_TYPE_QUAL:
+ prev_comp = NULL;
+ ret_comp = d_left (ret_comp);
+ break;
+ case D_COMP_NAME:
+ case D_COMP_TEMPLATE:
+ case D_COMP_CTOR:
+ case D_COMP_DTOR:
+ case D_COMP_OPERATOR:
+ case D_COMP_EXTENDED_OPERATOR:
+ done = 1;
+ break;
+ default:
+ done = 1;
+ prev_comp = NULL;
+ ret_comp = NULL;
+ break;
+ }
+
+ ret = NULL;
+ if (prev_comp != NULL)
{
- ret = xmalloc (end - demangled_name + 1);
- memcpy (ret, demangled_name, end - demangled_name);
- ret[end - demangled_name] = '\0';
+ *prev_comp = *d_left (prev_comp);
+ /* The ten is completely arbitrary; we don't have a good estimate. */
+ ret = cp_comp_to_string (prev_comp, 10);
}
+ cp_v3_d_free_info (di);
xfree (demangled_name);
return ret;
}
char *
method_name_from_physname (const char *physname)
{
- char *ret = NULL;
- const char *end;
- int depth = 0;
- char *demangled_name = cplus_demangle (physname, DMGL_ANSI | DMGL_PARAMS);
+ struct d_info *di;
+ char *demangled_name, *ret;
+ struct d_comp *ret_comp;
+ int done;
- if (demangled_name == NULL)
+ ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &di, &demangled_name);
+ if (ret_comp == NULL)
return NULL;
- end = find_last_component (demangled_name);
- if (end != NULL)
- {
- char *args;
- int len;
+ done = 0;
+ while (!done)
+ switch (ret_comp->type)
+ {
+ case D_COMP_QUAL_NAME:
+ case D_COMP_LOCAL_NAME:
+ case D_COMP_TYPED_NAME:
+ ret_comp = d_right (ret_comp);
+ break;
+ case D_COMP_CONST:
+ case D_COMP_RESTRICT:
+ case D_COMP_VOLATILE:
+ case D_COMP_CONST_THIS:
+ case D_COMP_RESTRICT_THIS:
+ case D_COMP_VOLATILE_THIS:
+ case D_COMP_VENDOR_TYPE_QUAL:
+ ret_comp = d_left (ret_comp);
+ break;
+ case D_COMP_NAME:
+ case D_COMP_TEMPLATE:
+ case D_COMP_CTOR:
+ case D_COMP_DTOR:
+ case D_COMP_OPERATOR:
+ case D_COMP_EXTENDED_OPERATOR:
+ done = 1;
+ break;
+ default:
+ done = 1;
+ ret_comp = NULL;
+ break;
+ }
- /* Skip "::". */
- end = end + 2;
-
- /* Find the argument list, if any. */
- args = strchr (end, '(');
- if (args == NULL)
- len = strlen (end + 2);
- else
- {
- args --;
- while (*args == ' ')
- args --;
- len = args - end + 1;
- }
- ret = xmalloc (len + 1);
- memcpy (ret, end, len);
- ret[len] = 0;
- }
+ ret = NULL;
+ if (ret_comp != NULL)
+ /* The ten is completely arbitrary; we don't have a good estimate. */
+ ret = cp_comp_to_string (ret_comp, 10);
+ cp_v3_d_free_info (di);
xfree (demangled_name);
return ret;
}
+/* Here are some random pieces of trivia to keep in mind while trying
+ to take apart demangled names:
+
+ - Names can contain function arguments or templates, so the process
+ has to be, to some extent recursive: maybe keep track of your
+ depth based on encountering <> and ().
+
+ - Parentheses don't just have to happen at the end of a name: they
+ can occur even if the name in question isn't a function, because
+ a template argument might be a type that's a function.
+
+ - Conversely, even if you're trying to deal with a function, its
+ demangled name might not end with ')': it could be a const or
+ volatile class method, in which case it ends with "const" or
+ "volatile".
+
+ - Parentheses are also used in anonymous namespaces: a variable
+ 'foo' in an anonymous namespace gets demangled as "(anonymous
+ namespace)::foo".
+
+ - And operator names can contain parentheses or angle brackets. */
+
+/* FIXME: carlton/2003-03-13: We have several functions here with
+ overlapping functionality; can we combine them? Also, do they
+ handle all the above considerations correctly? */
+
+
/* This returns the length of first component of NAME, which should be
the demangled name of a C++ variable/function/method/etc.
Specifically, it returns the index of the first colon forming the