From 8f793aa54168462d7525a44e83e6a56c7f362a5e Mon Sep 17 00:00:00 2001 From: Fred Fish Date: Tue, 5 May 1992 18:16:23 +0000 Subject: [PATCH] * Makefile.in (DEMANGLER): Define and default to cplus-dem. Allows selection of C++ demangler to be a configuration option until multiple demanglers are supported. * demangle.h: New include file for extended demangler support. * breakpoint.c, gdbtypes.c, printcmd.c, stack.c, symtab.c, utils.c, valprint.c: Include "demangle.h" and change all calls to cplus_demangle() or fputs_demangled() to use individual demangling options. * valprint.c (type_print_1): Change options to cplus_demangle to print demangled function args. Still broken, but now less so. * cplus-dem.c: Include demangle.h, reorganize and update some comments to reflect reality. * cplus-dem.c (cplus_demangle, cplus_mangle_opname): Change second arg from fixed integer to bit based multiple options. * cplus-dem.c (optable): Reformat and replace ansi members with bit based options. * cplus-dem.c (do_type): Fix bug with parsing missing return type. --- gdb/.Sanitize | 1 + gdb/ChangeLog | 20 ++++ gdb/cplus-dem.c | 266 +++++++++++++++++++++++++----------------------- gdb/demangle.h | 20 ++++ gdb/gdbtypes.c | 3 +- gdb/valprint.c | 20 ++-- gdb/values.c | 2 +- 7 files changed, 195 insertions(+), 137 deletions(-) create mode 100644 gdb/demangle.h diff --git a/gdb/.Sanitize b/gdb/.Sanitize index 50f103e0c8..f58f89cc81 100644 --- a/gdb/.Sanitize +++ b/gdb/.Sanitize @@ -72,6 +72,7 @@ cplus-dem.c createtags dbxread.c defs.h +demangle.h depend doc dwarfread.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bac88e44ca..1f2864c3f8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +Tue May 5 11:10:27 1992 Fred Fish (fnf@cygnus.com) + + * Makefile.in (DEMANGLER): Define and default to cplus-dem. + Allows selection of C++ demangler to be a configuration option + until multiple demanglers are supported. + * demangle.h: New include file for extended demangler support. + * breakpoint.c, gdbtypes.c, printcmd.c, stack.c, symtab.c, + utils.c, valprint.c: Include "demangle.h" and change all calls + to cplus_demangle() or fputs_demangled() to use individual + demangling options. + * valprint.c (type_print_1): Change options to cplus_demangle + to print demangled function args. Still broken, but now less so. + * cplus-dem.c: Include demangle.h, reorganize and update some + comments to reflect reality. + * cplus-dem.c (cplus_demangle, cplus_mangle_opname): Change + second arg from fixed integer to bit based multiple options. + * cplus-dem.c (optable): Reformat and replace ansi members with + bit based options. + * cplus-dem.c (do_type): Fix bug with parsing missing return type. + Mon May 4 22:26:59 1992 John Gilmore (gnu at cygnus.com) * values.c (set_internalvar): Force evaluation of lazy values. diff --git a/gdb/cplus-dem.c b/gdb/cplus-dem.c index d42c8b7b1a..ddd07e4a07 100644 --- a/gdb/cplus-dem.c +++ b/gdb/cplus-dem.c @@ -18,29 +18,7 @@ /* This is for g++ 1.95.03 (November 13 verison). */ -/* 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 - is returned. - - If MODE > 0, then ANSI qualifiers such as `const' and `void' are output. - Otherwise they are not. - If MODE >= 0, parameters are emitted; otherwise not. - - For example, - - 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 exports two functions; cplus_mangle_opname and cplus_demangle. This file imports xmalloc and xrealloc, which are like malloc and realloc except that they generate a fatal error if there is no @@ -51,6 +29,7 @@ /* GDB-specific, FIXME. */ #include "defs.h" +#include "demangle.h" #include @@ -73,16 +52,18 @@ #endif #ifdef __STDC__ -extern char *cplus_demangle (const char *type, int mode); +extern char *cplus_demangle (const char *type, int options); +extern char *cplus_mangle_opname (char *opname, int options); #else extern char *cplus_demangle (); +extern char *cplus_mangle_opname (); #endif /* Stuff that is shared betwen sub-routines. * Using a shared structure allows cplus_demange to be reentrant. */ struct work_stuff { - int arg_mode; + int options; char **typevec; int ntypes; int typevec_size; @@ -91,81 +72,82 @@ struct work_stuff { const static struct optable { const char *in; const char *out; - int ansi; + int flags; } optable[] = { - "nw", " new", 1, /* new (1.92, ansi) */ - "dl", " delete", 1, /* new (1.92, ansi) */ - "new", " new", 0, /* old (1.91, and 1.x) */ - "delete", " delete", 0, /* old (1.91, and 1.x) */ - "as", "=", 1, /* ansi */ - "ne", "!=", 1, /* old, ansi */ - "eq", "==", 1, /* old, ansi */ - "ge", ">=", 1, /* old, ansi */ - "gt", ">", 1, /* old, ansi */ - "le", "<=", 1, /* old, ansi */ - "lt", "<", 1, /* old, ansi */ - "plus", "+", 0, /* old */ - "pl", "+", 1, /* ansi */ - "apl", "+=", 1, /* ansi */ - "minus", "-", 0, /* old */ - "mi", "-", 1, /* ansi */ - "ami", "-=", 1, /* ansi */ - "mult", "*", 0, /* old */ - "ml", "*", 1, /* ansi */ - "aml", "*=", 1, /* ansi */ - "convert", "+", 0, /* old (unary +) */ - "negate", "-", 0, /* old (unary -) */ - "trunc_mod", "%", 0, /* old */ - "md", "%", 1, /* ansi */ - "amd", "%=", 1, /* ansi */ - "trunc_div", "/", 0, /* old */ - "dv", "/", 1, /* ansi */ - "adv", "/=", 1, /* ansi */ - "truth_andif", "&&", 0, /* old */ - "aa", "&&", 1, /* ansi */ - "truth_orif", "||", 0, /* old */ - "oo", "||", 1, /* ansi */ - "truth_not", "!", 0, /* old */ - "nt", "!", 1, /* ansi */ - "postincrement", "++", 0, /* old */ - "pp", "++", 1, /* ansi */ - "postdecrement", "--", 0, /* old */ - "mm", "--", 1, /* ansi */ - "bit_ior", "|", 0, /* old */ - "or", "|", 1, /* ansi */ - "aor", "|=", 1, /* ansi */ - "bit_xor", "^", 0, /* old */ - "er", "^", 1, /* ansi */ - "aer", "^=", 1, /* ansi */ - "bit_and", "&", 0, /* old */ - "ad", "&", 1, /* ansi */ - "aad", "&=", 1, /* ansi */ - "bit_not", "~", 0, /* old */ - "co", "~", 1, /* ansi */ - "call", "()", 0, /* old */ - "cl", "()", 1, /* ansi */ - "alshift", "<<", 0, /* old */ - "ls", "<<", 1, /* ansi */ - "als", "<<=", 1, /* ansi */ - "arshift", ">>", 0, /* old */ - "rs", ">>", 1, /* ansi */ - "ars", ">>=", 1, /* ansi */ - "component", "->", 0, /* old */ - "rf", "->", 1, /* ansi */ - "indirect", "*", 0, /* old */ - "method_call", "->()", 0, /* old */ - "addr", "&", 0, /* old (unary &) */ - "array", "[]", 0, /* old */ - "vc", "[]", 1, /* ansi */ - "compound", ",", 0, /* old */ - "cm", ",", 1, /* ansi */ - "cond", "?:", 0, /* old */ - "cn", "?:", 1, /* psuedo-ansi */ - "max", ">?", 0, /* old */ - "mx", ">?", 1, /* psuedo-ansi */ - "min", "=", DMGL_ANSI, /* old, ansi */ + "gt", ">", DMGL_ANSI, /* old, ansi */ + "le", "<=", DMGL_ANSI, /* old, ansi */ + "lt", "<", DMGL_ANSI, /* old, ansi */ + "plus", "+", 0, /* old */ + "pl", "+", DMGL_ANSI, /* ansi */ + "apl", "+=", DMGL_ANSI, /* ansi */ + "minus", "-", 0, /* old */ + "mi", "-", DMGL_ANSI, /* ansi */ + "ami", "-=", DMGL_ANSI, /* ansi */ + "mult", "*", 0, /* old */ + "ml", "*", DMGL_ANSI, /* ansi */ + "aml", "*=", DMGL_ANSI, /* ansi */ + "convert", "+", 0, /* old (unary +) */ + "negate", "-", 0, /* old (unary -) */ + "trunc_mod", "%", 0, /* old */ + "md", "%", DMGL_ANSI, /* ansi */ + "amd", "%=", DMGL_ANSI, /* ansi */ + "trunc_div", "/", 0, /* old */ + "dv", "/", DMGL_ANSI, /* ansi */ + "adv", "/=", DMGL_ANSI, /* ansi */ + "truth_andif", "&&", 0, /* old */ + "aa", "&&", DMGL_ANSI, /* ansi */ + "truth_orif", "||", 0, /* old */ + "oo", "||", DMGL_ANSI, /* ansi */ + "truth_not", "!", 0, /* old */ + "nt", "!", DMGL_ANSI, /* ansi */ + "postincrement","++", 0, /* old */ + "pp", "++", DMGL_ANSI, /* ansi */ + "postdecrement","--", 0, /* old */ + "mm", "--", DMGL_ANSI, /* ansi */ + "bit_ior", "|", 0, /* old */ + "or", "|", DMGL_ANSI, /* ansi */ + "aor", "|=", DMGL_ANSI, /* ansi */ + "bit_xor", "^", 0, /* old */ + "er", "^", DMGL_ANSI, /* ansi */ + "aer", "^=", DMGL_ANSI, /* ansi */ + "bit_and", "&", 0, /* old */ + "ad", "&", DMGL_ANSI, /* ansi */ + "aad", "&=", DMGL_ANSI, /* ansi */ + "bit_not", "~", 0, /* old */ + "co", "~", DMGL_ANSI, /* ansi */ + "call", "()", 0, /* old */ + "cl", "()", DMGL_ANSI, /* ansi */ + "alshift", "<<", 0, /* old */ + "ls", "<<", DMGL_ANSI, /* ansi */ + "als", "<<=", DMGL_ANSI, /* ansi */ + "arshift", ">>", 0, /* old */ + "rs", ">>", DMGL_ANSI, /* ansi */ + "ars", ">>=", DMGL_ANSI, /* ansi */ + "component", "->", 0, /* old */ + "rf", "->", DMGL_ANSI, /* ansi */ + "indirect", "*", 0, /* old */ + "method_call", "->()", 0, /* old */ + "addr", "&", 0, /* old (unary &) */ + "array", "[]", 0, /* old */ + "vc", "[]", DMGL_ANSI, /* ansi */ + "compound", ", ", 0, /* old */ + "cm", ", ", DMGL_ANSI, /* ansi */ + "cond", "?:", 0, /* old */ + "cn", "?:", DMGL_ANSI, /* psuedo-ansi */ + "max", ">?", 0, /* old */ + "mx", ">?", DMGL_ANSI, /* psuedo-ansi */ + "min", "*", DMGL_ANSI, /* ansi */ }; /* Beware: these aren't '\0' terminated. */ @@ -233,32 +215,55 @@ string_prepends PARAMS ((string *, string *)); /* Takes operator name as e.g. "++" and returns mangled operator name (e.g. "postincrement_expr"), or NULL if not found. - If ARG_MODE == 1, return the ANSI name; - if ARG_MODE == 0 return the old GNU name. */ + If OPTIONS & DMGL_ANSI == 1, return the ANSI name; + if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */ + char * -cplus_mangle_opname (opname, arg_mode) +cplus_mangle_opname (opname, options) char *opname; - int arg_mode; + int options; { int i, len = strlen (opname); - if (arg_mode != 0 && arg_mode != 1) - error ("invalid arg_mode"); - - for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) + for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { if (strlen (optable[i].out) == len - && arg_mode == optable[i].ansi + && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI) && memcmp (optable[i].out, opname, len) == 0) return (char *)optable[i].in; } return 0; } +/* char *cplus_demangle (const char *name, int options) + + 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 + is returned. + + The OPTIONS arg may contain one or more of the following bits: + + DMGL_ANSI ANSI qualifiers such as `const' and `void' are + included. + DMGL_PARAMS Function parameters are included. + + For example, + + cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" + cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" + cplus_demangle ("foo__1Ai", 0) => "A::foo" + + cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" + cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" + cplus_demangle ("foo__1Afe", 0) => "A::foo" + */ + char * -cplus_demangle (type, arg_mode) +cplus_demangle (type, options) const char *type; - int arg_mode; + int options; { string decl; int n; @@ -274,8 +279,8 @@ cplus_demangle (type, arg_mode) const char *premangle; #endif -# define print_ansi_qualifiers (work->arg_mode > 0) -# define print_arg_types (work->arg_mode >= 0) +# define PRINT_ANSI_QUALIFIERS (work->options & DMGL_ANSI) +# define PRINT_ARG_TYPES (work->options & DMGL_PARAMS) if (type == NULL || *type == '\0') return NULL; @@ -284,7 +289,7 @@ cplus_demangle (type, arg_mode) return NULL; #endif - work->arg_mode = arg_mode; + work->options = options; work->typevec = NULL; work->ntypes = 0; work->typevec_size = 0; @@ -311,7 +316,7 @@ cplus_demangle (type, arg_mode) strcpy (tem, type); strcat (tem, "::~"); strcat (tem, type); - if (print_arg_types) + if (PRINT_ARG_TYPES) strcat (tem, "()"); return tem; } @@ -357,7 +362,7 @@ cplus_demangle (type, arg_mode) string_appendn (&decl, type, p - type); string_need (&decl, 1); *(decl.p) = '\0'; - munge_function_name (&decl, work); /* arg_mode=1 ?? */ + munge_function_name (&decl, work); /* options ?? */ if (decl.b[0] == '_') { string_delete (&decl); @@ -471,7 +476,7 @@ cplus_demangle (type, arg_mode) } else success = do_args (&p, &decl, work); - if (const_flag && print_arg_types) + if (const_flag && PRINT_ARG_TYPES) string_append (&decl, " const"); break; case 'F': @@ -777,9 +782,12 @@ do_type (type, result, work) string_prepend (&decl, "("); string_append (&decl, ")"); } - if (!do_args (type, &decl, work) || **type != '_') + /* After picking off the function args, we expect to either find the + function type (preceded by an '_') or the end of the string. */ + if (!do_args (type, &decl, work) + || (**type != '_' && **type != '\0')) success = 0; - else + if (success && (**type == '_')) *type += 1; break; @@ -838,7 +846,7 @@ do_type (type, result, work) break; } *type += 1; - if (! print_ansi_qualifiers) + if (! PRINT_ANSI_QUALIFIERS) break; if (constp) { @@ -863,7 +871,7 @@ do_type (type, result, work) if ((*type)[1] == 'P') { *type += 1; - if (print_ansi_qualifiers) + if (PRINT_ANSI_QUALIFIERS) { if (!string_empty (&decl)) string_prepend (&decl, " "); @@ -887,7 +895,7 @@ do_type (type, result, work) { case 'C': *type += 1; - if (print_ansi_qualifiers) + if (PRINT_ANSI_QUALIFIERS) { if (non_empty) string_append (result, " "); @@ -914,7 +922,7 @@ do_type (type, result, work) break; case 'V': *type += 1; - if (print_ansi_qualifiers) + if (PRINT_ANSI_QUALIFIERS) { if (non_empty) string_append (result, " "); @@ -1103,7 +1111,7 @@ do_args (type, decl, work) string arg; int need_comma = 0; - if (print_arg_types) + if (PRINT_ARG_TYPES) string_append (decl, "("); while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v') @@ -1118,11 +1126,11 @@ do_args (type, decl, work) while (--r >= 0) { const char *tem = work->typevec[t]; - if (need_comma && print_arg_types) + if (need_comma && PRINT_ARG_TYPES) string_append (decl, ", "); if (!do_arg (&tem, &arg, work)) return 0; - if (print_arg_types) + if (PRINT_ARG_TYPES) string_appends (decl, &arg); string_delete (&arg); need_comma = 1; @@ -1130,11 +1138,11 @@ do_args (type, decl, work) } else { - if (need_comma & print_arg_types) + if (need_comma & PRINT_ARG_TYPES) string_append (decl, ", "); if (!do_arg (type, &arg, work)) return 0; - if (print_arg_types) + if (PRINT_ARG_TYPES) string_appends (decl, &arg); string_delete (&arg); need_comma = 1; @@ -1146,7 +1154,7 @@ do_args (type, decl, work) else if (**type == 'e') { *type += 1; - if (print_arg_types) + if (PRINT_ARG_TYPES) { if (need_comma) string_append (decl, ","); @@ -1154,7 +1162,7 @@ do_args (type, decl, work) } } - if (print_arg_types) + if (PRINT_ARG_TYPES) string_append (decl, ")"); return 1; } diff --git a/gdb/demangle.h b/gdb/demangle.h new file mode 100644 index 0000000000..71cdb80183 --- /dev/null +++ b/gdb/demangle.h @@ -0,0 +1,20 @@ +/* Demangler defs for GNU C++ style demangling. + Copyright 1992 Free Software Foundation, Inc. + + 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) + any later version. + + 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. */ + + +#define DMGL_PARAMS (1 << 0) /* Include function args */ +#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 2523c7697f..77a26bc78a 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -29,6 +29,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "language.h" #include "target.h" #include "value.h" +#include "demangle.h" /* Alloc a new type structure and fill it with some defaults. If OBJFILE is non-NULL, then allocate the space for the type structure @@ -739,7 +740,7 @@ check_stub_method (type, i, j) { struct fn_field *f; char *mangled_name = gdb_mangle_name (type, i, j); - char *demangled_name = cplus_demangle (mangled_name, 0); + char *demangled_name = cplus_demangle (mangled_name, DMGL_PARAMS); char *argtypetext, *p; int depth = 0, argcount = 1; struct type **argtypes; diff --git a/gdb/valprint.c b/gdb/valprint.c index 1675eb1155..6492f1dc20 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -27,6 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "target.h" #include "obstack.h" #include "language.h" +#include "demangle.h" #include @@ -1032,7 +1033,8 @@ val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty) if ((msymbol != NULL) && (vt_address == msymbol -> address)) { fputs_filtered (" <", stream); - fputs_demangled (msymbol -> name, stream, 1); + fputs_demangled (msymbol -> name, stream, + DMGL_ANSI | DMGL_PARAMS); fputs_filtered (">", stream); } if (vtblprint) @@ -1363,8 +1365,12 @@ type_print_1 (type, varstring, stream, show, level) || code == TYPE_CODE_REF))) fprintf_filtered (stream, " "); type_print_varspec_prefix (type, stream, show, 0); - fputs_demangled (varstring, stream, -1); /* Print demangled name - without arguments */ + /* FIXME: Previously this printed demangled names without function args, + which is a lose since you can't distinguish between overloaded function + names (try "info func" for example). This change is still not optimal, + since you now get a superflous pair of parens for functions, but at + least you can distinguish them. */ + fputs_demangled (varstring, stream, DMGL_PARAMS); type_print_varspec_suffix (type, stream, show, 0); } @@ -1378,8 +1384,8 @@ type_print_method_args (args, prefix, varstring, staticp, stream) { int i; - fputs_demangled (prefix, stream, 1); - fputs_demangled (varstring, stream, 1); + fputs_demangled (prefix, stream, DMGL_ANSI | DMGL_PARAMS); + fputs_demangled (varstring, stream, DMGL_ANSI | DMGL_PARAMS); fputs_filtered (" (", stream); if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID) { @@ -1790,7 +1796,9 @@ type_print_base (type, stream, show, level) { /* Build something we can demangle. */ char *mangled_name = gdb_mangle_name (type, i, j); - char *demangled_name = cplus_demangle (mangled_name, 1); + char *demangled_name = + cplus_demangle (mangled_name, + DMGL_ANSI | DMGL_PARAMS); if (demangled_name == 0) fprintf_filtered (stream, "", mangled_name); diff --git a/gdb/values.c b/gdb/values.c index 08c970b7f2..b2fc150d12 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -1070,7 +1070,7 @@ value_headof (arg, btype, dtype) { pc_for_sym = value_as_pointer (value_field (best_entry, 2)); sym = find_pc_function (pc_for_sym); - demangled_name = cplus_demangle (SYMBOL_NAME (sym), -1); + demangled_name = cplus_demangle (SYMBOL_NAME (sym), 0); *(strchr (demangled_name, ':')) = '\0'; } sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0);