* 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.
This commit is contained in:
Per Bothner 1997-09-17 03:38:30 +00:00
parent 1a6eb36b62
commit fc655dc202
6 changed files with 347 additions and 48 deletions

View File

@ -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):

View File

@ -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)
{

View File

@ -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 ()
{

View File

@ -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 *));

View File

@ -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))

View File

@ -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))
{
fprintf_filtered (stream, "(");
type_print (TYPE_TARGET_TYPE (type), "", stream, -1);
fprintf_filtered (stream, ") ");
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);
}
}
return (val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
VALUE_ADDRESS (val) + VALUE_OFFSET (val),
if (TYPE_CODE (type) == TYPE_CODE_PTR && ! value_logical_not (val))
{
type_print (TYPE_TARGET_TYPE (type), "", stream, -1);
}
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))
{
CORE_ADDR obj_addr = unpack_pointer (type, valaddr);
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);
}
}
switch (TYPE_CODE (type))
{
case TYPE_CODE_PTR:
if (format && format != 's')
{
print_scalar_formatted (valaddr, type, format, 0, stream);
break;
}
#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);