aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPer Bothner <per@bothner.com>1997-09-17 03:38:30 +0000
committerPer Bothner <per@bothner.com>1997-09-17 03:38:30 +0000
commitfc655dc202bb59777269eeb2331aac40049140c2 (patch)
treedaa8e68446981dcd6e2dc3662a22a8ca60e123ed
parent1a6eb36b628c19e1064c342f98a7f6cb9eb3033a (diff)
downloadfsf-binutils-gdb-fc655dc202bb59777269eeb2331aac40049140c2.zip
fsf-binutils-gdb-fc655dc202bb59777269eeb2331aac40049140c2.tar.gz
fsf-binutils-gdb-fc655dc202bb59777269eeb2331aac40049140c2.tar.bz2
* 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.
-rw-r--r--gdb/ChangeLog18
-rw-r--r--gdb/jv-exp.y164
-rw-r--r--gdb/jv-lang.c100
-rw-r--r--gdb/jv-lang.h2
-rw-r--r--gdb/jv-typeprint.c19
-rw-r--r--gdb/jv-valprint.c88
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);