diff options
Diffstat (limited to 'gdb/jv-typeprint.c')
-rw-r--r-- | gdb/jv-typeprint.c | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/gdb/jv-typeprint.c b/gdb/jv-typeprint.c new file mode 100644 index 00000000000..59539a0da9f --- /dev/null +++ b/gdb/jv-typeprint.c @@ -0,0 +1,339 @@ +/* Support for printing Java types for GDB, the GNU debugger. + Copyright 1997, 1998, 1999 Free Software Foundation, Inc. + +This file is part of GDB. + +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 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "value.h" +#include "demangle.h" +#include "jv-lang.h" +#include "gdb_string.h" +#include "typeprint.h" + +static void +java_type_print_derivation_info (stream, type) + GDB_FILE *stream; + struct type *type; +{ + char *name; + int i; + int n_bases; + int prev; + + n_bases = TYPE_N_BASECLASSES (type); + + for (i = 0, prev = 0; i < n_bases; i++) + { + int kind; + + kind = BASETYPE_VIA_VIRTUAL(type, i) ? 'I' : 'E'; + + fputs_filtered (kind == prev ? ", " + : kind == 'I' ? " implements " + : " extends ", + stream); + prev = kind; + name = type_name_no_tag (TYPE_BASECLASS (type, i)); + + fprintf_filtered (stream, "%s", name ? name : "(null)"); + } + + if (i > 0) + fputs_filtered (" ", stream); +} + +/* Print the name of the type (or the ultimate pointer target, + function value or array element), or the description of a + structure or union. + + SHOW positive means print details about the type (e.g. enum values), + and print structure elements passing SHOW - 1 for show. + SHOW negative means just print the type name or struct tag if there is one. + If there is no name, print something sensible but concise like + "struct {...}". + SHOW zero means just print the type name or struct tag if there is one. + If there is no name, print something sensible but not as concise like + "struct {int x; int y;}". + + LEVEL is the number of spaces to indent by. + We increase it for some recursive calls. */ + +void +java_type_print_base (type, stream, show, level) + struct type *type; + GDB_FILE *stream; + int show; + int level; +{ + register int i; + register int len; + char *mangled_name; + char *demangled_name; + QUIT; + + wrap_here (" "); + + if (type == NULL) + { + fputs_filtered ("<type unknown>", stream); + return; + } + + /* When SHOW is zero or less, and there is a valid type name, then always + just print the type name directly from the type. */ + + if (show <= 0 + && TYPE_NAME (type) != NULL) + { + fputs_filtered (TYPE_NAME (type), stream); + return; + } + + CHECK_TYPEDEF (type); + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_PTR: + java_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); + break; + + case TYPE_CODE_STRUCT: + if (TYPE_TAG_NAME (type) != NULL && TYPE_TAG_NAME (type)[0] == '[') + { /* array type */ + char *name = java_demangle_type_signature (TYPE_TAG_NAME (type)); + fputs_filtered (name, stream); + free (name); + break; + } + + if (show >= 0) + fprintf_filtered (stream, "class "); + + if (TYPE_TAG_NAME (type) != NULL) + { + fputs_filtered (TYPE_TAG_NAME (type), stream); + if (show > 0) + fputs_filtered (" ", stream); + } + + wrap_here (" "); + + if (show < 0) + { + /* If we just printed a tag name, no need to print anything else. */ + if (TYPE_TAG_NAME (type) == NULL) + fprintf_filtered (stream, "{...}"); + } + else if (show > 0 || TYPE_TAG_NAME (type) == NULL) + { + java_type_print_derivation_info (stream, type); + + fprintf_filtered (stream, "{\n"); + if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0)) + if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) + fprintfi_filtered (level + 4, stream, "<incomplete type>\n"); + else + fprintfi_filtered (level + 4, stream, "<no data fields>\n"); + + /* If there is a base class for this type, + do not print the field that it occupies. */ + + len = TYPE_NFIELDS (type); + for (i = TYPE_N_BASECLASSES (type); i < len; i++) + { + QUIT; + /* Don't print out virtual function table. */ + if (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5) + && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5])) + continue; + + /* Don't print the dummy field "class". */ + if (STREQN (TYPE_FIELD_NAME (type, i), "class", 5)) + continue; + + print_spaces_filtered (level + 4, stream); + + if (HAVE_CPLUS_STRUCT (type)) + if (TYPE_FIELD_PROTECTED (type, i)) + fprintf_filtered (stream, "protected "); + else if (TYPE_FIELD_PRIVATE (type, i)) + fprintf_filtered (stream, "private "); + else + fprintf_filtered (stream, "public "); + + if (TYPE_FIELD_STATIC (type, i)) + fprintf_filtered (stream, "static "); + + java_print_type (TYPE_FIELD_TYPE (type, i), + TYPE_FIELD_NAME (type, i), + stream, show - 1, level + 4); + + fprintf_filtered (stream, ";\n"); + } + + /* If there are both fields and methods, put a space between. */ + len = TYPE_NFN_FIELDS (type); + if (len) + fprintf_filtered (stream, "\n"); + + /* Print out the methods */ + + for (i = 0; i < len; i++) + { + struct fn_field *f; + int j; + char *method_name; + char *name; + int is_constructor; + int n_overloads; + + f = TYPE_FN_FIELDLIST1 (type, i); + n_overloads = TYPE_FN_FIELDLIST_LENGTH (type, i); + method_name = TYPE_FN_FIELDLIST_NAME (type, i); + name = type_name_no_tag (type); + is_constructor = name && STREQ (method_name, name); + + for (j = 0; j < n_overloads; j++) + { + char *physname; + int is_full_physname_constructor; + + physname = TYPE_FN_FIELD_PHYSNAME (f, j); + + is_full_physname_constructor = + ((physname[0] == '_' && physname[1] == '_' + && strchr ("0123456789Qt", physname[2])) + || STREQN (physname, "__ct__", 6) + || DESTRUCTOR_PREFIX_P (physname) + || STREQN (physname, "__dt__", 6)); + + QUIT; + + print_spaces_filtered (level + 4, stream); + + if (TYPE_FN_FIELD_PROTECTED (f, j)) + fprintf_filtered (stream, "protected "); + else if (TYPE_FN_FIELD_PRIVATE (f, j)) + fprintf_filtered (stream, "private "); + else if (TYPE_FN_FIELD_PUBLIC (f, j)) + fprintf_filtered (stream, "public "); + + if (TYPE_FN_FIELD_ABSTRACT (f, j)) + fprintf_filtered (stream, "abstract "); + if (TYPE_FN_FIELD_STATIC (f, j)) + fprintf_filtered (stream, "static "); + if (TYPE_FN_FIELD_FINAL (f, j)) + fprintf_filtered (stream, "final "); + if (TYPE_FN_FIELD_SYNCHRONIZED (f, j)) + fprintf_filtered (stream, "synchronized "); + if (TYPE_FN_FIELD_NATIVE (f, j)) + fprintf_filtered (stream, "native "); + + if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0) + { + /* Keep GDB from crashing here. */ + fprintf_filtered (stream, "<undefined type> %s;\n", + TYPE_FN_FIELD_PHYSNAME (f, j)); + break; + } + else if (!is_constructor && !is_full_physname_constructor) + { + type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), + "", stream, -1); + fputs_filtered (" ", stream); + } + + if (TYPE_FN_FIELD_STUB (f, j)) + /* Build something we can demangle. */ + mangled_name = gdb_mangle_name (type, i, j); + else + mangled_name = TYPE_FN_FIELD_PHYSNAME (f, j); + + demangled_name = + cplus_demangle (mangled_name, + DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA); + + if (demangled_name == NULL) + demangled_name = strdup (mangled_name); + + { + char *demangled_no_class; + char *ptr; + + ptr = demangled_no_class = demangled_name; + + while (1) + { + char c; + + c = *ptr++; + + if (c == 0 || c == '(') + break; + if (c == '.') + demangled_no_class = ptr; + } + + fputs_filtered (demangled_no_class, stream); + free (demangled_name); + } + + if (TYPE_FN_FIELD_STUB (f, j)) + free (mangled_name); + + fprintf_filtered (stream, ";\n"); + } + } + + fprintfi_filtered (level, stream, "}"); + } + break; + + default: + c_type_print_base (type, stream, show, level); + } +} + +/* LEVEL is the depth to indent lines by. */ + +void +java_print_type (type, varstring, stream, show, level) + struct type *type; + char *varstring; + GDB_FILE *stream; + int show; + int level; +{ + int demangled_args; + + java_type_print_base (type, stream, show, level); + + if (varstring != NULL && *varstring != '\0') + { + fputs_filtered (" ", stream); + fputs_filtered (varstring, stream); + } + + /* For demangled function names, we have the arglist as part of the name, + so don't print an additional pair of ()'s */ + + demangled_args = strchr(varstring, '(') != NULL; + c_type_print_varspec_suffix (type, stream, show, 0, demangled_args); +} |