]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
* jv-exp.y (push_fieldnames): New, to handle EXP.FIELD1....FIELDN.
authorPer Bothner <per@bothner.com>
Wed, 17 Sep 1997 03:38:30 +0000 (03:38 +0000)
committerPer Bothner <per@bothner.com>
Wed, 17 Sep 1997 03:38:30 +0000 (03:38 +0000)
(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.

gdb/ChangeLog
gdb/jv-exp.y
gdb/jv-lang.c
gdb/jv-lang.h
gdb/jv-typeprint.c
gdb/jv-valprint.c

index 1149607b9d3a696522dbc2a994933eb49392dbcf..91757b370e1df7ec4819d2b0a1f8b3ae8725fd9b 100644 (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):
index d20499385461f3f18230239fa4ff172bc724441a..22067a6b53f6f7512f77c4633f7951112b5c58cc 100644 (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)
     {
index 22a810af6e42c5871af3fe28e77bc3474ee3b5b9..2c0f7f137d8922060a60b602c00efdb7fcd6bd8a 100644 (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 ()
 {
index b2417eebb6ec30afe314adbb2d1ab13fe98593c1..caaba44ae02fc8f99d6bd529bffc864d49345eeb 100644 (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 *));
index b3a20cc0ed555ad8cd9674182e6f9e4600b5e572..4c5a204183d330a8cba66268a41b82dba68f3864 100644 (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))
index 06ea084b6b65cf73d88dac60d92238eabf1d3683..b4afa1ec97f3cc93d6d5d63a121ad256eb03f37d 100644 (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))
+    {
+      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);