diff options
-rw-r--r-- | gdb/ChangeLog | 18 | ||||
-rw-r--r-- | gdb/jv-exp.y | 164 | ||||
-rw-r--r-- | gdb/jv-lang.c | 100 | ||||
-rw-r--r-- | gdb/jv-lang.h | 2 | ||||
-rw-r--r-- | gdb/jv-typeprint.c | 19 | ||||
-rw-r--r-- | gdb/jv-valprint.c | 88 |
6 files changed, 345 insertions, 46 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1149607..91757b3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,21 @@ +Tue Sep 16 20:00:05 1997 Per Bothner <bothner@cygnus.com> + + * jv-exp.y (push_fieldnames): New, to handle EXP.FIELD1....FIELDN. + (push_expression_name): New, to handle expression names. + (push_qualified_expression_name): New, for qualified expression names. + (parse_number): Fix bugs in parsing of non-decimal integers. + * jv-lang.h, jv-lang.c (java_demangle_type_signature): New. + * jv-lang.c (type_from_class): Just use name with java_lookup_class. + (java_link_class_type): Add dummy "class" field. + (java_lookup_type): New. + (evaluate_subexp_java case STRUCTOP_STRUCT): Force to address. + * jv-typeprint.c (java_type_print_base): Don't print "class" field. + Use java_demangle_type_signature to print array class types. + * jv-valprint.c (java_value_print): Preliminary array support. + Print pointer as TYPE@HEXADDR, instead of (TYPE)0xHEXADDR. + (java_val_print): Move check for object type to java_value_print. + Check for null. Print pointer as @HEXADDR, not 0xHEXADDR. + Tue Sep 16 19:56:23 1997 Per Bothner <bothner@cygnus.com> * util.c (run_cleanup_chain, make_run_cleanup, do_run_cleanups): diff --git a/gdb/jv-exp.y b/gdb/jv-exp.y index d204993..22067a6 100644 --- a/gdb/jv-exp.y +++ b/gdb/jv-exp.y @@ -109,7 +109,8 @@ void yyerror PARAMS ((char *)); static struct type * java_type_from_name PARAMS ((struct stoken)); -static void push_variable PARAMS ((struct stoken)); +static void push_expression_name PARAMS ((struct stoken)); +static void push_fieldnames PARAMS ((struct stoken)); %} @@ -424,9 +425,7 @@ Dims_opt: FieldAccess: Primary '.' SimpleName - { write_exp_elt_opcode (STRUCTOP_STRUCT); - write_exp_string ($3); - write_exp_elt_opcode (STRUCTOP_STRUCT); } + { push_fieldnames ($3); } /*| SUPER '.' SimpleName { FIXME } */ ; @@ -441,15 +440,18 @@ MethodInvocation: ArrayAccess: Name '[' Expression ']' - { error ("ArrayAccess"); } /* FIXME - NASTY */ + /* FIXME - This is nasty - need to shuffle expr stack. */ + { error ("`Name[Expr]' not implemented yet - try `(Name)[Expr]'"); } | PrimaryNoNewArray '[' Expression ']' - { write_exp_elt_opcode (BINOP_SUBSCRIPT); } + { + warning("array subscripts not implemented for Java"); + write_exp_elt_opcode (BINOP_SUBSCRIPT); } ; PostfixExpression: Primary | Name - { push_variable ($1); } + { push_expression_name ($1); } | VARIABLE /* Already written by write_dollar_variable. */ | PostIncrementExpression @@ -608,7 +610,7 @@ Assignment: LeftHandSide: ForcedName - { push_variable ($1); } + { push_expression_name ($1); } | VARIABLE /* Already written by write_dollar_variable. */ | FieldAccess @@ -735,15 +737,12 @@ parse_number (p, len, parsed_float, putithere) c = *p++; if (c >= '0' && c <= '9') c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; else - { - if (c >= 'A' && c <= 'Z') - c += 'a' - 'A'; - if (c >= 'a' && c - 'a' + 10 < base) - c -= 'a' + 10; - else - return ERROR; /* Char not a digit */ - } + return ERROR; /* Char not a digit */ if (c >= base) return ERROR; if (n > limit_div_base @@ -1163,7 +1162,10 @@ java_type_from_name (name) return typ; } -static void +/* If NAME is a valid variable name in this scope, push it and return 1. + Otherwise, return 0. */ + +static int push_variable (name) struct stoken name; @@ -1171,10 +1173,9 @@ push_variable (name) char *tmp = copy_name (name); int is_a_field_of_this = 0; struct symbol *sym; - struct type *typ; sym = lookup_symbol (tmp, expression_context_block, VAR_NAMESPACE, &is_a_field_of_this, (struct symtab **) NULL); - if (sym) + if (sym && SYMBOL_CLASS (sym) != LOC_TYPEDEF) { if (symbol_read_needs_frame (sym)) { @@ -1189,7 +1190,7 @@ push_variable (name) write_exp_elt_block (NULL); write_exp_elt_sym (sym); write_exp_elt_opcode (OP_VAR_VALUE); - return; + return 1; } if (is_a_field_of_this) { @@ -1203,9 +1204,132 @@ push_variable (name) write_exp_elt_opcode (STRUCTOP_PTR); write_exp_string (name); write_exp_elt_opcode (STRUCTOP_PTR); + return 1; + } + return 0; +} + +/* Assuming a reference expression has been pushed, emit the + STRUCTOP_STRUCT ops to access the field named NAME. If NAME is a + qualified name (has '.'), generate a field access for each part. */ + +static void +push_fieldnames (name) + struct stoken name; +{ + int i; + struct stoken token; + token.ptr = name.ptr; + for (i = 0; ; i++) + { + if (i == name.length || name.ptr[i] == '.') + { + /* token.ptr is start of current field name. */ + token.length = &name.ptr[i] - token.ptr; + write_exp_elt_opcode (STRUCTOP_STRUCT); + write_exp_string (token); + write_exp_elt_opcode (STRUCTOP_STRUCT); + token.ptr += token.length + 1; + } + if (i >= name.length) + break; + } +} + +/* Helper routine for push_expression_name. + Handle a qualified name, where DOT_INDEX is the index of the first '.' */ + +static void +push_qualified_expression_name (name, dot_index) + struct stoken name; + int dot_index; +{ + struct stoken token; + char *tmp; + struct type *typ; + + token.ptr = name.ptr; + token.length = dot_index; + + if (push_variable (token)) + { + token.ptr = name.ptr + dot_index + 1; + token.length = name.length - dot_index - 1; + push_fieldnames (token); return; } + token.ptr = name.ptr; + for (;;) + { + token.length = dot_index; + tmp = copy_name (token); + typ = java_lookup_class (tmp); + if (typ != NULL) + { + if (dot_index == name.length) + { + write_exp_elt_opcode(OP_TYPE); + write_exp_elt_type(typ); + write_exp_elt_opcode(OP_TYPE); + return; + } + dot_index++; /* Skip '.' */ + name.ptr += dot_index; + name.length -= dot_index; + while (dot_index < name.length && name.ptr[dot_index] != '.') + dot_index++; + token.ptr = name.ptr; + token.length = dot_index; + write_exp_elt_opcode (OP_SCOPE); + write_exp_elt_type (typ); + write_exp_string (token); + write_exp_elt_opcode (OP_SCOPE); + if (dot_index < name.length) + { + dot_index++; + name.ptr += dot_index; + name.length -= dot_index; + push_fieldnames (name); + } + return; + } + else if (dot_index >= name.length) + break; + dot_index++; /* Skip '.' */ + while (dot_index < name.length && name.ptr[dot_index] != '.') + dot_index++; + } + error ("unknown type `%.*s'", name.length, name.ptr); +} + +/* Handle Name in an expression (or LHS). + Handle VAR, TYPE, TYPE.FIELD1....FIELDN and VAR.FIELD1....FIELDN. */ + +static void +push_expression_name (name) + struct stoken name; +{ + char *tmp; + struct type *typ; + char *ptr; + int i; + + for (i = 0; i < name.length; i++) + { + if (name.ptr[i] == '.') + { + /* It's a Qualified Expression Name. */ + push_qualified_expression_name (name, i); + return; + } + } + + /* It's a Simple Expression Name. */ + + if (push_variable (name)) + return; + tmp = copy_name (name); typ = java_lookup_class (tmp); if (typ != NULL) { diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c index 22a810a..2c0f7f1 100644 --- a/gdb/jv-lang.c +++ b/gdb/jv-lang.c @@ -236,7 +236,7 @@ type_from_class (clas) struct type *type; char *name; value_ptr temp; - struct objfile *objfile = get_dynamics_objfile(); + struct objfile *objfile; value_ptr utf8_name; char *nptr; CORE_ADDR addr; @@ -253,6 +253,7 @@ type_from_class (clas) } addr = VALUE_ADDRESS (clas) + VALUE_OFFSET (clas); +#if 0 get_java_class_symtab (); bl = BLOCKVECTOR_BLOCK (BLOCKVECTOR (class_symtab), GLOBAL_BLOCK); for (i = BLOCK_NSYMS (bl); --i >= 0; ) @@ -261,7 +262,9 @@ type_from_class (clas) if (SYMBOL_VALUE_ADDRESS (sym) == addr) return SYMBOL_TYPE (sym); } +#endif + objfile = get_dynamics_objfile(); if (java_class_is_primitive (clas)) { value_ptr sig; @@ -275,6 +278,15 @@ type_from_class (clas) temp = clas; utf8_name = value_struct_elt (&temp, NULL, "name", NULL, "structure"); name = get_java_utf8_name (&objfile->type_obstack, utf8_name); + for (nptr = name; *nptr != 0; nptr++) + { + if (*nptr == '/') + *nptr = '.'; + } + + type = java_lookup_class (name); + if (type != NULL) + return type; type = alloc_type (objfile); TYPE_CODE (type) = TYPE_CODE_STRUCT; @@ -289,11 +301,6 @@ type_from_class (clas) VALUE_TYPE (temp) = lookup_pointer_type (VALUE_TYPE (clas)); TYPE_TARGET_TYPE (type) = type_from_class (temp); } - for (nptr = name; *nptr != 0; nptr++) - { - if (*nptr == '/') - *nptr = '.'; - } ALLOCATE_CPLUS_STRUCT_TYPE (type); TYPE_NAME (type) = name; @@ -347,6 +354,7 @@ java_link_class_type (type, clas) temp = clas; nfields = value_as_long (value_struct_elt (&temp, NULL, "nfields", NULL, "structure")); nfields += TYPE_N_BASECLASSES (type); + nfields++; /* Add one for dummy "class" field. */ TYPE_NFIELDS (type) = nfields; TYPE_FIELDS (type) = (struct field *) TYPE_ALLOC (type, sizeof (struct field) * nfields); @@ -382,6 +390,13 @@ java_link_class_type (type, clas) TYPE_LENGTH (type) = value_as_long (temp); fields = NULL; + nfields--; /* First set up dummy "class" field. */ + SET_FIELD_PHYSADDR (TYPE_FIELD (type, nfields), + VALUE_ADDRESS (clas) + VALUE_OFFSET (clas)); + TYPE_FIELD_NAME (type, nfields) = "super"; + TYPE_FIELD_TYPE (type, nfields) = VALUE_TYPE (clas); + SET_TYPE_FIELD_PRIVATE (type, nfields); + for (i = TYPE_N_BASECLASSES (type); i < nfields; i++) { int accflags; @@ -574,6 +589,68 @@ java_primitive_type (signature) error ("unknown signature '%c' for primitive type", (char) signature); } +/* Return the demangled name of the Java type signature string SIGNATURE, + as a freshly allocated copy. */ + +char * +java_demangle_type_signature (signature) + char *signature; +{ + int array = 0; + char *result; + char *ptr; + int i; + while (*signature == '[') + { + array++; + signature++; + } + switch (signature[0]) + { + case 'L': + /* Substract 2 for 'L' and ';', but add 1 for final nul. */ + result = xmalloc (strlen (signature) - 1 + 2 * array); + signature++; + ptr = result; + for ( ; *signature != ';' && *signature != '\0'; signature++) + { + if (*signature == '/') + *ptr++ = '.'; + else + *ptr++ = *signature; + } + break; + default: + ptr = TYPE_NAME (java_primitive_type (signature[0])); + i = strlen (ptr); + result = xmalloc (i + 1 + 2 * array); + strcpy (result, ptr); + ptr = result + i; + break; + } + while (--array >= 0) + { + *ptr++ = '['; + *ptr++ = ']'; + } + *ptr = '\0'; + return result; +} + +struct type * +java_lookup_type (signature) + char *signature; +{ + switch (signature[0]) + { + case 'L': + case '[': + error ("java_lookup_type not fully inmplemented"); + default: + return java_primitive_type (signature[0]); + } +} + /* Return the type of TYPE followed by DIMS pairs of [ ]. If DIMS == 0, TYPE is returned. */ @@ -630,6 +707,12 @@ evaluate_subexp_java (expect_type, exp, pos, noside) if (noside == EVAL_SKIP) goto nosideret; return java_value_string (&exp->elts[pc + 2].string, i); + case STRUCTOP_STRUCT: + arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside); + /* Convert object field (such as .class) to reference. */ + if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT) + arg1 = value_addr (arg1); + return arg1; default: break; } @@ -742,8 +825,9 @@ _initialize_jave_language () add_language (&java_language_defn); } -/* Cleanup code that should be urn on every "run". - We need some hook to have this actually be called ... FIXME */ +/* Cleanup code that should be run on every "run". + We should use make_run_cleanup to have this be called. + But will that mess up values in value histry? FIXME */ void java_rerun_cleanup () { diff --git a/gdb/jv-lang.h b/gdb/jv-lang.h index b2417ee..caaba44 100644 --- a/gdb/jv-lang.h +++ b/gdb/jv-lang.h @@ -64,3 +64,5 @@ extern int is_object_type PARAMS ((struct type*)); extern void /* Defined in jv-typeprint.c */ java_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int)); + +extern char * java_demangle_type_signature PARAMS ((char *)); diff --git a/gdb/jv-typeprint.c b/gdb/jv-typeprint.c index b3a20cc..4c5a204 100644 --- a/gdb/jv-typeprint.c +++ b/gdb/jv-typeprint.c @@ -103,8 +103,20 @@ java_type_print_base (type, stream, show, level) switch (TYPE_CODE (type)) { + case TYPE_CODE_PTR: + java_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); + break; + case TYPE_CODE_STRUCT: - fprintf_filtered (stream, "class "); + if (TYPE_TAG_NAME (type) != NULL && TYPE_TAG_NAME (type)[0] == '[') + { /* array type */ + char *name = java_demangle_type_signature (TYPE_TAG_NAME (type)); + fputs (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); @@ -143,8 +155,9 @@ java_type_print_base (type, stream, show, level) && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5])) continue; - /* If this is a C++ class we can print the various C++ section - labels. */ + /* 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)) diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c index 06ea084..b4afa1e 100644 --- a/gdb/jv-valprint.c +++ b/gdb/jv-valprint.c @@ -36,14 +36,35 @@ java_value_print (val, stream, format, pretty) enum val_prettyprint pretty; { struct type *type = VALUE_TYPE (val); - if (TYPE_CODE (type) == TYPE_CODE_PTR) + CORE_ADDR address = VALUE_ADDRESS (val) + VALUE_OFFSET (val); + if (is_object_type (type)) + { + CORE_ADDR obj_addr = unpack_pointer (type, VALUE_CONTENTS (val)); + if (obj_addr != 0) + { + value_ptr obj_val + = value_at (TYPE_TARGET_TYPE (type), obj_addr, NULL); + type = type_from_class (java_class_from_object (obj_val)); + type = lookup_pointer_type (type); + } + } + if (TYPE_CODE (type) == TYPE_CODE_PTR && ! value_logical_not (val)) { - fprintf_filtered (stream, "("); type_print (TYPE_TARGET_TYPE (type), "", stream, -1); - fprintf_filtered (stream, ") "); } - return (val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), - VALUE_ADDRESS (val) + VALUE_OFFSET (val), + + if (TYPE_CODE (type) == TYPE_CODE_STRUCT && TYPE_TAG_NAME (type) != NULL + && TYPE_TAG_NAME (type)[0] == '[') + { + value_ptr len = value_at (java_int_type, address + JAVA_OBJECT_SIZE, 0); + long length = value_as_long (len); + fprintf_filtered (stream, "{"); + fprintf_filtered (stream, "length = %ld", length); + fprintf_filtered (stream, "}"); + return 0; + } + + return (val_print (type, VALUE_CONTENTS (val), address, stream, format, 1, 0, pretty)); } @@ -59,20 +80,57 @@ java_val_print (type, valaddr, address, stream, format, deref_ref, recurse, int recurse; enum val_prettyprint pretty; { + register unsigned int i = 0; /* Number of characters printed */ + struct type *elttype; + CORE_ADDR addr; + CHECK_TYPEDEF (type); - if (is_object_type (type)) + switch (TYPE_CODE (type)) { - CORE_ADDR obj_addr = unpack_pointer (type, valaddr); - if (obj_addr != 0) + case TYPE_CODE_PTR: + if (format && format != 's') { - value_ptr obj_val - = value_at (TYPE_TARGET_TYPE (type), obj_addr, NULL); - type = type_from_class (java_class_from_object (obj_val)); - type = lookup_pointer_type (type); + print_scalar_formatted (valaddr, type, format, 0, stream); + break; } - } - switch (TYPE_CODE (type)) - { +#if 0 + if (vtblprint && cp_is_vtbl_ptr_type(type)) + { + /* Print the unmangled name if desired. */ + /* Print vtable entry - we only get here if we ARE using + -fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */ + print_address_demangle(extract_address (valaddr, TYPE_LENGTH (type)), + stream, demangle); + break; + } +#endif + addr = unpack_pointer (type, valaddr); + if (addr == 0) + { + fputs_filtered ("null", stream); + return i; + } + elttype = check_typedef (TYPE_TARGET_TYPE (type)); + { + print_unpacked_pointer: + elttype = check_typedef (TYPE_TARGET_TYPE (type)); + + if (TYPE_CODE (elttype) == TYPE_CODE_FUNC) + { + /* Try to print what function it points to. */ + print_address_demangle (addr, stream, demangle); + /* Return value is irrelevant except for string pointers. */ + return (0); + } + + if (addressprint && format != 's') + { + fputs_filtered ("@", stream); + print_longest (stream, 'x', 0, (ULONGEST) addr); + } + return i; + } + break; default: return c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty); |