This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 6/7] Move language stuff out of varobj.c


On 09/18/2013 09:54 PM, Yao Qi wrote:
> This patch moves language-related stuff out of varobj.c into
> c-varobj.c, jv-varobj.c and ada-varobj.c respectively.  This patch
> also makes some static functions extern and add "varobj_" prefix.

The new patch 4/7 affects this patch.  I post the updated one.  Patch
7/7 is not affected, so it can be reviewed too.

-- 
Yao (éå)

gdb:

2013-10-11  Yao Qi  <yao@codesourcery.com>

	* Makefile.in (SFILES): Add c-varobj.c and jv-varobj.c.
	(COMMON_OBS): Add c-varobj.o and jv-varobj.o.
	* ada-varobj.c: Include "varobj.h".
	(ada_number_of_children): New.  Moved from varobj.c.
	(ada_name_of_variable, ada_name_of_child): Likewise.
	(ada_path_expr_of_child, ada_value_of_child): Likewise.
	(ada_type_of_child, ada_value_of_variable): Likewise.
	(ada_value_is_changeable_p, ada_value_has_mutated): Likewise.
	(ada_varobj_ops): New.
	* c-varobj.c, jv-varobj.c: New file.  Moved from varobj.c.
	* gdbtypes.c (get_target_type): New.  Moved from varobj.c.
	* gdbtypes.h (get_target_type): Declare.
	* varobj.c: Remove the inclusion of "ada-varobj.h" and
	"ada-lang.h".
	(ANONYMOUS_STRUCT_NAME): Move it to c-varobj.c.
	(ANONYMOUS_UNION_NAME): Likewise.
	(get_type, get_value_type, get_target_type): Remove declarations.
	(value_get_print_value, varobj_value_get_print_value): Likewise.
	(c_number_of_children, c_name_of_variable): Likewise.
	(c_name_of_child, c_path_expr_of_child): Likewise.
	(c_value_of_child, c_type_of_child): Likewise.
	(c_value_of_variable, cplus_number_of_children): Likewise.
	(cplus_class_num_children, cplus_name_of_variable): Likewise.
	(cplus_name_of_child, cplus_path_expr_of_child): Likewise.
	(cplus_value_of_child, cplus_type_of_child): Likewise.
	(cplus_value_of_variable, java_number_of_children): Likewise.
	(java_name_of_variable, java_name_of_child): Likewise.
	(java_path_expr_of_child, java_value_of_child): Likewise.
	(java_type_of_child, java_value_of_variable): Likewise.
	(ada_number_of_children, ada_name_of_variable): Likewise.
	(ada_name_of_child, ada_path_expr_of_child): Likewise.
	(ada_value_of_child, ada_type_of_child): Likewise.
	(ada_value_of_variable, ada_value_is_changeable_p): Likewise.
	(ada_value_has_mutated): Likewise.
	(struct language_specific): Move it to varobj.h.
	(CPLUS_FAKE_CHILD): Move it to varobj.h.
	(restrict_range): Rename it varobj_restrict_range.  Make it extern.
	Callers update.
	(get_path_expr_parent): Rename it to varobj_get_path_expr_parent.
	Make it extern.
	(is_anonymous_child): Move it to c-varobj.c and rename to
	varobj_is_anonymous_child.  Caller update.
	(get_type): Move it to c-varobj.c.
	(get_value_type): Rename it varobj_get_value_type.  Make it
	extern.
	(get_target_type): Move it gdbtypes.c.
	(varobj_formatted_print_options): New function.
	(value_get_print_value): Rename it to
	varobj_value_get_print_value and make it extern.
	(varobj_value_is_changeable_p): Make it extern.
	(adjust_value_for_child_access): Move it to c-varobj.c.
	(default_value_is_changeable_p): Rename it to
	varobj_default_value_is_changeable_p.  Make it extern.
	(c_number_of_children, c_name_of_variable): Move it to c-varobj.c
	(c_name_of_child, c_path_expr_of_child): Likewise.
	(c_value_of_child, c_type_of_child): Likewise.
	(c_value_of_variable, cplus_number_of_children): Likewise.
	(cplus_class_num_children, cplus_name_of_variable): Likewise.
	(cplus_name_of_child, cplus_path_expr_of_child): Likewise.
	(cplus_value_of_child, cplus_type_of_child): Likewise.
	(cplus_value_of_variable): Likewise.
	(java_number_of_children, java_name_of_variable): Move it to jv-varobj.c.
	(java_name_of_child, java_path_expr_of_child): Likewise.
	(java_value_of_child, java_type_of_child): Likewise.
	(java_value_of_variable): Likewise.
	(ada_number_of_children, ada_name_of_variable): Move it to ada-varobj.c.
	(ada_name_of_child, ada_path_expr_of_child): Likewise.
	(ada_value_of_child, ada_type_of_child): Likewise.
	(ada_value_of_variable, ada_value_is_changeable_p): Likewise.
	(ada_value_has_mutated): Likewise.
	* varobj.h (CPLUS_FAKE_CHILD): New macro, moved from varobj.c.
	(struct lang_varobj_ops): New.  Renamed by 'struct language_specific'.
	(c_varobj_ops, cplus_varobj_ops): Declare.
	(java_varobj_ops, ada_varobj_ops): Declare.
	(varobj_default_value_is_changeable_p): Declare.
	(varobj_value_is_changeable_p): Declare.
	(varobj_get_value_type, varobj_is_anonymous_child): Declare.
	(varobj_get_path_expr_parent): Declare.
	(varobj_value_get_print_value): Declare.
	(varobj_formatted_print_options): Declare.
	(varobj_restrict_range): Declare.
---
 gdb/Makefile.in  |    8 +-
 gdb/ada-varobj.c |  137 ++++++
 gdb/c-varobj.c   |  910 +++++++++++++++++++++++++++++++++++++
 gdb/gdbtypes.c   |   16 +
 gdb/gdbtypes.h   |    4 +
 gdb/jv-varobj.c  |  105 +++++
 gdb/varobj.c     | 1328 ++----------------------------------------------------
 gdb/varobj.h     |   80 ++++
 8 files changed, 1300 insertions(+), 1288 deletions(-)
 create mode 100644 gdb/c-varobj.c
 create mode 100644 gdb/jv-varobj.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 2aa8134..c2d9b71 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -718,7 +718,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	block.c blockframe.c \
 	breakpoint.c break-catch-sig.c break-catch-throw.c \
 	build-id.c buildsym.c \
-	c-exp.y c-lang.c c-typeprint.c c-valprint.c \
+	c-exp.y c-lang.c c-typeprint.c c-valprint.c c-varobj.c \
 	charset.c cleanups.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c continuations.c corefile.c corelow.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
@@ -739,7 +739,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	infcmd.c inflow.c infrun.c \
 	inline-frame.c \
 	interps.c \
-	jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \
+	jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c jv-varobj.c \
 	language.c linespec.c minidebug.c \
 	m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c \
 	macrotab.c macroexp.c macrocmd.c macroscope.c main.c maint.c \
@@ -923,11 +923,11 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o dwarf2-frame-tailcall.o \
 	ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
-	ada-tasks.o ada-varobj.o \
+	ada-tasks.o ada-varobj.o c-varobj.o \
 	ui-out.o cli-out.o \
 	varobj.o vec.o \
 	go-lang.o go-valprint.o go-typeprint.o \
-	jv-lang.o jv-valprint.o jv-typeprint.o \
+	jv-lang.o jv-valprint.o jv-typeprint.o jv-varobj.o \
 	m2-lang.o opencl-lang.o p-lang.o p-typeprint.o p-valprint.o \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
diff --git a/gdb/ada-varobj.c b/gdb/ada-varobj.c
index 53d8a9c..52c7687 100644
--- a/gdb/ada-varobj.c
+++ b/gdb/ada-varobj.c
@@ -20,6 +20,7 @@
 #include "defs.h"
 #include "ada-varobj.h"
 #include "ada-lang.h"
+#include "varobj.h"
 #include "language.h"
 #include "valprint.h"
 
@@ -885,4 +886,140 @@ ada_varobj_get_value_of_variable (struct value *value,
   return result;
 }
 
+/* Ada specific callbacks for VAROBJs.  */
 
+static int
+ada_number_of_children (struct varobj *var)
+{
+  return ada_varobj_get_number_of_children (var->value, var->type);
+}
+
+static char *
+ada_name_of_variable (struct varobj *parent)
+{
+  return c_varobj_ops.name_of_variable (parent);
+}
+
+static char *
+ada_name_of_child (struct varobj *parent, int index)
+{
+  return ada_varobj_get_name_of_child (parent->value, parent->type,
+				       parent->name, index);
+}
+
+static char*
+ada_path_expr_of_child (struct varobj *child)
+{
+  struct varobj *parent = child->parent;
+  const char *parent_path_expr = varobj_get_path_expr (parent);
+
+  return ada_varobj_get_path_expr_of_child (parent->value,
+					    parent->type,
+					    parent->name,
+					    parent_path_expr,
+					    child->index);
+}
+
+static struct value *
+ada_value_of_child (struct varobj *parent, int index)
+{
+  return ada_varobj_get_value_of_child (parent->value, parent->type,
+					parent->name, index);
+}
+
+static struct type *
+ada_type_of_child (struct varobj *parent, int index)
+{
+  return ada_varobj_get_type_of_child (parent->value, parent->type,
+				       index);
+}
+
+static char *
+ada_value_of_variable (struct varobj *var, enum varobj_display_formats format)
+{
+  struct value_print_options opts;
+
+  varobj_formatted_print_options (&opts, format);
+
+  return ada_varobj_get_value_of_variable (var->value, var->type, &opts);
+}
+
+/* Implement the "value_is_changeable_p" routine for Ada.  */
+
+static int
+ada_value_is_changeable_p (struct varobj *var)
+{
+  struct type *type = var->value ? value_type (var->value) : var->type;
+
+  if (ada_is_array_descriptor_type (type)
+      && TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+    {
+      /* This is in reality a pointer to an unconstrained array.
+	 its value is changeable.  */
+      return 1;
+    }
+
+  if (ada_is_string_type (type))
+    {
+      /* We display the contents of the string in the array's
+	 "value" field.  The contents can change, so consider
+	 that the array is changeable.  */
+      return 1;
+    }
+
+  return varobj_default_value_is_changeable_p (var);
+}
+
+/* Implement the "value_has_mutated" routine for Ada.  */
+
+static int
+ada_value_has_mutated (struct varobj *var, struct value *new_val,
+		       struct type *new_type)
+{
+  int i;
+  int from = -1;
+  int to = -1;
+
+  /* If the number of fields have changed, then for sure the type
+     has mutated.  */
+  if (ada_varobj_get_number_of_children (new_val, new_type)
+      != var->num_children)
+    return 1;
+
+  /* If the number of fields have remained the same, then we need
+     to check the name of each field.  If they remain the same,
+     then chances are the type hasn't mutated.  This is technically
+     an incomplete test, as the child's type might have changed
+     despite the fact that the name remains the same.  But we'll
+     handle this situation by saying that the child has mutated,
+     not this value.
+
+     If only part (or none!) of the children have been fetched,
+     then only check the ones we fetched.  It does not matter
+     to the frontend whether a child that it has not fetched yet
+     has mutated or not. So just assume it hasn't.  */
+
+  varobj_restrict_range (var->children, &from, &to);
+  for (i = from; i < to; i++)
+    if (strcmp (ada_varobj_get_name_of_child (new_val, new_type,
+					      var->name, i),
+		VEC_index (varobj_p, var->children, i)->name) != 0)
+      return 1;
+
+  return 0;
+}
+
+/* varobj operations for ada.  */
+
+const struct lang_varobj_ops ada_varobj_ops =
+{
+  ada_number_of_children,
+  ada_name_of_variable,
+  ada_name_of_child,
+  ada_path_expr_of_child,
+  ada_value_of_child,
+  ada_type_of_child,
+  ada_value_of_variable,
+  ada_value_is_changeable_p,
+  ada_value_has_mutated
+};
diff --git a/gdb/c-varobj.c b/gdb/c-varobj.c
new file mode 100644
index 0000000..73e785c
--- /dev/null
+++ b/gdb/c-varobj.c
@@ -0,0 +1,910 @@
+/* varobj support for C and C++.
+
+   Copyright (C) 1999-2013 Free Software Foundation, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "value.h"
+#include "varobj.h"
+#include "gdbthread.h"
+#include "valprint.h"
+
+static void cplus_class_num_children (struct type *type, int children[3]);
+
+/* The names of varobjs representing anonymous structs or unions.  */
+#define ANONYMOUS_STRUCT_NAME _("<anonymous struct>")
+#define ANONYMOUS_UNION_NAME _("<anonymous union>")
+
+/* Does CHILD represent a child with no name?  This happens when
+   the child is an anonmous struct or union and it has no field name
+   in its parent variable.
+
+   This has already been determined by *_describe_child. The easiest
+   thing to do is to compare the child's name with ANONYMOUS_*_NAME.  */
+
+int
+varobj_is_anonymous_child (struct varobj *child)
+{
+  return (strcmp (child->name, ANONYMOUS_STRUCT_NAME) == 0
+	  || strcmp (child->name, ANONYMOUS_UNION_NAME) == 0);
+}
+
+/* Given the value and the type of a variable object,
+   adjust the value and type to those necessary
+   for getting children of the variable object.
+   This includes dereferencing top-level references
+   to all types and dereferencing pointers to
+   structures.
+
+   If LOOKUP_ACTUAL_TYPE is set the enclosing type of the
+   value will be fetched and if it differs from static type
+   the value will be casted to it.
+
+   Both TYPE and *TYPE should be non-null.  VALUE
+   can be null if we want to only translate type.
+   *VALUE can be null as well -- if the parent
+   value is not known.
+
+   If WAS_PTR is not NULL, set *WAS_PTR to 0 or 1
+   depending on whether pointer was dereferenced
+   in this function.  */
+
+static void
+adjust_value_for_child_access (struct value **value,
+				  struct type **type,
+				  int *was_ptr,
+				  int lookup_actual_type)
+{
+  gdb_assert (type && *type);
+
+  if (was_ptr)
+    *was_ptr = 0;
+
+  *type = check_typedef (*type);
+  
+  /* The type of value stored in varobj, that is passed
+     to us, is already supposed to be
+     reference-stripped.  */
+
+  gdb_assert (TYPE_CODE (*type) != TYPE_CODE_REF);
+
+  /* Pointers to structures are treated just like
+     structures when accessing children.  Don't
+     dererences pointers to other types.  */
+  if (TYPE_CODE (*type) == TYPE_CODE_PTR)
+    {
+      struct type *target_type = get_target_type (*type);
+      if (TYPE_CODE (target_type) == TYPE_CODE_STRUCT
+	  || TYPE_CODE (target_type) == TYPE_CODE_UNION)
+	{
+	  if (value && *value)
+	    {
+	      volatile struct gdb_exception except;
+
+	      TRY_CATCH (except, RETURN_MASK_ERROR)
+		{
+		  *value = value_ind (*value);
+		}
+
+	      if (except.reason < 0)
+		*value = NULL;
+	    }
+	  *type = target_type;
+	  if (was_ptr)
+	    *was_ptr = 1;
+	}
+    }
+
+  /* The 'get_target_type' function calls check_typedef on
+     result, so we can immediately check type code.  No
+     need to call check_typedef here.  */
+
+  /* Access a real type of the value (if necessary and possible).  */
+  if (value && *value && lookup_actual_type)
+    {
+      struct type *enclosing_type;
+      int real_type_found = 0;
+
+      enclosing_type = value_actual_type (*value, 1, &real_type_found);
+      if (real_type_found)
+        {
+          *type = enclosing_type;
+          *value = value_cast (enclosing_type, *value);
+        }
+    }
+}
+
+/* C */
+
+static int
+c_number_of_children (struct varobj *var)
+{
+  struct type *type = varobj_get_value_type (var);
+  int children = 0;
+  struct type *target;
+
+  adjust_value_for_child_access (NULL, &type, NULL, 0);
+  target = get_target_type (type);
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_ARRAY:
+      if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (target) > 0
+	  && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
+	children = TYPE_LENGTH (type) / TYPE_LENGTH (target);
+      else
+	/* If we don't know how many elements there are, don't display
+	   any.  */
+	children = 0;
+      break;
+
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      children = TYPE_NFIELDS (type);
+      break;
+
+    case TYPE_CODE_PTR:
+      /* The type here is a pointer to non-struct.  Typically, pointers
+	 have one child, except for function ptrs, which have no children,
+	 and except for void*, as we don't know what to show.
+
+         We can show char* so we allow it to be dereferenced.  If you decide
+         to test for it, please mind that a little magic is necessary to
+         properly identify it: char* has TYPE_CODE == TYPE_CODE_INT and 
+         TYPE_NAME == "char".  */
+      if (TYPE_CODE (target) == TYPE_CODE_FUNC
+	  || TYPE_CODE (target) == TYPE_CODE_VOID)
+	children = 0;
+      else
+	children = 1;
+      break;
+
+    default:
+      /* Other types have no children.  */
+      break;
+    }
+
+  return children;
+}
+
+static char *
+c_name_of_variable (struct varobj *parent)
+{
+  return xstrdup (parent->name);
+}
+
+/* Return the value of element TYPE_INDEX of a structure
+   value VALUE.  VALUE's type should be a structure,
+   or union, or a typedef to struct/union.
+
+   Returns NULL if getting the value fails.  Never throws.  */
+
+static struct value *
+value_struct_element_index (struct value *value, int type_index)
+{
+  struct value *result = NULL;
+  volatile struct gdb_exception e;
+  struct type *type = value_type (value);
+
+  type = check_typedef (type);
+
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
+	      || TYPE_CODE (type) == TYPE_CODE_UNION);
+
+  TRY_CATCH (e, RETURN_MASK_ERROR)
+    {
+      if (field_is_static (&TYPE_FIELD (type, type_index)))
+	result = value_static_field (type, type_index);
+      else
+	result = value_primitive_field (value, 0, type_index, type);
+    }
+  if (e.reason < 0)
+    {
+      return NULL;
+    }
+  else
+    {
+      return result;
+    }
+}
+
+/* Obtain the information about child INDEX of the variable
+   object PARENT.
+   If CNAME is not null, sets *CNAME to the name of the child relative
+   to the parent.
+   If CVALUE is not null, sets *CVALUE to the value of the child.
+   If CTYPE is not null, sets *CTYPE to the type of the child.
+
+   If any of CNAME, CVALUE, or CTYPE is not null, but the corresponding
+   information cannot be determined, set *CNAME, *CVALUE, or *CTYPE
+   to NULL.  */
+
+static void 
+c_describe_child (struct varobj *parent, int index,
+		  char **cname, struct value **cvalue, struct type **ctype,
+		  char **cfull_expression)
+{
+  struct value *value = parent->value;
+  struct type *type = varobj_get_value_type (parent);
+  char *parent_expression = NULL;
+  int was_ptr;
+  volatile struct gdb_exception except;
+
+  if (cname)
+    *cname = NULL;
+  if (cvalue)
+    *cvalue = NULL;
+  if (ctype)
+    *ctype = NULL;
+  if (cfull_expression)
+    {
+      *cfull_expression = NULL;
+      parent_expression
+	= varobj_get_path_expr (varobj_get_path_expr_parent (parent));
+    }
+  adjust_value_for_child_access (&value, &type, &was_ptr, 0);
+      
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_ARRAY:
+      if (cname)
+	*cname
+	  = xstrdup (int_string (index 
+				 + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
+				 10, 1, 0, 0));
+
+      if (cvalue && value)
+	{
+	  int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
+
+	  TRY_CATCH (except, RETURN_MASK_ERROR)
+	    {
+	      *cvalue = value_subscript (value, real_index);
+	    }
+	}
+
+      if (ctype)
+	*ctype = get_target_type (type);
+
+      if (cfull_expression)
+	*cfull_expression = 
+	  xstrprintf ("(%s)[%s]", parent_expression, 
+		      int_string (index
+				  + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
+				  10, 1, 0, 0));
+
+
+      break;
+
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      {
+	const char *field_name;
+
+	/* If the type is anonymous and the field has no name,
+	   set an appropriate name.  */
+	field_name = TYPE_FIELD_NAME (type, index);
+	if (field_name == NULL || *field_name == '\0')
+	  {
+	    if (cname)
+	      {
+		if (TYPE_CODE (TYPE_FIELD_TYPE (type, index))
+		    == TYPE_CODE_STRUCT)
+		  *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
+		else
+		  *cname = xstrdup (ANONYMOUS_UNION_NAME);
+	      }
+
+	    if (cfull_expression)
+	      *cfull_expression = xstrdup ("");
+	  }
+	else
+	  {
+	    if (cname)
+	      *cname = xstrdup (field_name);
+
+	    if (cfull_expression)
+	      {
+		char *join = was_ptr ? "->" : ".";
+
+		*cfull_expression = xstrprintf ("(%s)%s%s", parent_expression,
+						join, field_name);
+	      }
+	  }
+
+	if (cvalue && value)
+	  {
+	    /* For C, varobj index is the same as type index.  */
+	    *cvalue = value_struct_element_index (value, index);
+	  }
+
+	if (ctype)
+	  *ctype = TYPE_FIELD_TYPE (type, index);
+      }
+      break;
+
+    case TYPE_CODE_PTR:
+      if (cname)
+	*cname = xstrprintf ("*%s", parent->name);
+
+      if (cvalue && value)
+	{
+	  TRY_CATCH (except, RETURN_MASK_ERROR)
+	    {
+	      *cvalue = value_ind (value);
+	    }
+
+	  if (except.reason < 0)
+	    *cvalue = NULL;
+	}
+
+      /* Don't use get_target_type because it calls
+	 check_typedef and here, we want to show the true
+	 declared type of the variable.  */
+      if (ctype)
+	*ctype = TYPE_TARGET_TYPE (type);
+
+      if (cfull_expression)
+	*cfull_expression = xstrprintf ("*(%s)", parent_expression);
+      
+      break;
+
+    default:
+      /* This should not happen.  */
+      if (cname)
+	*cname = xstrdup ("???");
+      if (cfull_expression)
+	*cfull_expression = xstrdup ("???");
+      /* Don't set value and type, we don't know then.  */
+    }
+}
+
+static char *
+c_name_of_child (struct varobj *parent, int index)
+{
+  char *name;
+
+  c_describe_child (parent, index, &name, NULL, NULL, NULL);
+  return name;
+}
+
+static char *
+c_path_expr_of_child (struct varobj *child)
+{
+  c_describe_child (child->parent, child->index, NULL, NULL, NULL, 
+		    &child->path_expr);
+  return child->path_expr;
+}
+
+static struct value *
+c_value_of_child (struct varobj *parent, int index)
+{
+  struct value *value = NULL;
+
+  c_describe_child (parent, index, NULL, &value, NULL, NULL);
+  return value;
+}
+
+static struct type *
+c_type_of_child (struct varobj *parent, int index)
+{
+  struct type *type = NULL;
+
+  c_describe_child (parent, index, NULL, NULL, &type, NULL);
+  return type;
+}
+
+/* This returns the type of the variable.  It also skips past typedefs
+   to return the real type of the variable.  */
+
+static struct type *
+get_type (struct varobj *var)
+{
+  struct type *type;
+
+  type = var->type;
+  if (type != NULL)
+    type = check_typedef (type);
+
+  return type;
+}
+
+static char *
+c_value_of_variable (struct varobj *var, enum varobj_display_formats format)
+{
+  /* BOGUS: if val_print sees a struct/class, or a reference to one,
+     it will print out its children instead of "{...}".  So we need to
+     catch that case explicitly.  */
+  struct type *type = get_type (var);
+
+  /* Strip top-level references.  */
+  while (TYPE_CODE (type) == TYPE_CODE_REF)
+    type = check_typedef (TYPE_TARGET_TYPE (type));
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      return xstrdup ("{...}");
+      /* break; */
+
+    case TYPE_CODE_ARRAY:
+      {
+	char *number;
+
+	number = xstrprintf ("[%d]", var->num_children);
+	return (number);
+      }
+      /* break; */
+
+    default:
+      {
+	if (var->value == NULL)
+	  {
+	    /* This can happen if we attempt to get the value of a struct
+	       member when the parent is an invalid pointer.  This is an
+	       error condition, so we should tell the caller.  */
+	    return NULL;
+	  }
+	else
+	  {
+	    if (var->not_fetched && value_lazy (var->value))
+	      /* Frozen variable and no value yet.  We don't
+		 implicitly fetch the value.  MI response will
+		 use empty string for the value, which is OK.  */
+	      return NULL;
+
+	    gdb_assert (varobj_value_is_changeable_p (var));
+	    gdb_assert (!value_lazy (var->value));
+	    
+	    /* If the specified format is the current one,
+	       we can reuse print_value.  */
+	    if (format == var->format)
+	      return xstrdup (var->print_value);
+	    else
+	      return varobj_value_get_print_value (var->value, format, var);
+	  }
+      }
+    }
+}
+
+
+/* varobj operations for c.  */
+
+const struct lang_varobj_ops c_varobj_ops =
+{
+   c_number_of_children,
+   c_name_of_variable,
+   c_name_of_child,
+   c_path_expr_of_child,
+   c_value_of_child,
+   c_type_of_child,
+   c_value_of_variable,
+   varobj_default_value_is_changeable_p,
+   NULL /* value_has_mutated */
+};
+
+/* A little convenience enum for dealing with C++/Java.  */
+enum vsections
+{
+  v_public = 0, v_private, v_protected
+};
+
+/* C++ */
+
+static int
+cplus_number_of_children (struct varobj *var)
+{
+  struct value *value = NULL;
+  struct type *type;
+  int children, dont_know;
+  int lookup_actual_type = 0;
+  struct value_print_options opts;
+
+  dont_know = 1;
+  children = 0;
+
+  get_user_print_options (&opts);
+
+  if (!CPLUS_FAKE_CHILD (var))
+    {
+      type = varobj_get_value_type (var);
+
+      /* It is necessary to access a real type (via RTTI).  */
+      if (opts.objectprint)
+        {
+          value = var->value;
+          lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
+				|| TYPE_CODE (var->type) == TYPE_CODE_PTR);
+        }
+      adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
+
+      if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
+	  ((TYPE_CODE (type)) == TYPE_CODE_UNION))
+	{
+	  int kids[3];
+
+	  cplus_class_num_children (type, kids);
+	  if (kids[v_public] != 0)
+	    children++;
+	  if (kids[v_private] != 0)
+	    children++;
+	  if (kids[v_protected] != 0)
+	    children++;
+
+	  /* Add any baseclasses.  */
+	  children += TYPE_N_BASECLASSES (type);
+	  dont_know = 0;
+
+	  /* FIXME: save children in var.  */
+	}
+    }
+  else
+    {
+      int kids[3];
+
+      type = varobj_get_value_type (var->parent);
+
+      /* It is necessary to access a real type (via RTTI).  */
+      if (opts.objectprint)
+        {
+	  struct varobj *parent = var->parent;
+
+	  value = parent->value;
+	  lookup_actual_type = (TYPE_CODE (parent->type) == TYPE_CODE_REF
+				|| TYPE_CODE (parent->type) == TYPE_CODE_PTR);
+        }
+      adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
+
+      cplus_class_num_children (type, kids);
+      if (strcmp (var->name, "public") == 0)
+	children = kids[v_public];
+      else if (strcmp (var->name, "private") == 0)
+	children = kids[v_private];
+      else
+	children = kids[v_protected];
+      dont_know = 0;
+    }
+
+  if (dont_know)
+    children = c_number_of_children (var);
+
+  return children;
+}
+
+/* Compute # of public, private, and protected variables in this class.
+   That means we need to descend into all baseclasses and find out
+   how many are there, too.  */
+
+static void
+cplus_class_num_children (struct type *type, int children[3])
+{
+  int i, vptr_fieldno;
+  struct type *basetype = NULL;
+
+  children[v_public] = 0;
+  children[v_private] = 0;
+  children[v_protected] = 0;
+
+  vptr_fieldno = get_vptr_fieldno (type, &basetype);
+  for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
+    {
+      /* If we have a virtual table pointer, omit it.  Even if virtual
+	 table pointers are not specifically marked in the debug info,
+	 they should be artificial.  */
+      if ((type == basetype && i == vptr_fieldno)
+	  || TYPE_FIELD_ARTIFICIAL (type, i))
+	continue;
+
+      if (TYPE_FIELD_PROTECTED (type, i))
+	children[v_protected]++;
+      else if (TYPE_FIELD_PRIVATE (type, i))
+	children[v_private]++;
+      else
+	children[v_public]++;
+    }
+}
+
+static char *
+cplus_name_of_variable (struct varobj *parent)
+{
+  return c_name_of_variable (parent);
+}
+
+enum accessibility { private_field, protected_field, public_field };
+
+/* Check if field INDEX of TYPE has the specified accessibility.
+   Return 0 if so and 1 otherwise.  */
+
+static int 
+match_accessibility (struct type *type, int index, enum accessibility acc)
+{
+  if (acc == private_field && TYPE_FIELD_PRIVATE (type, index))
+    return 1;
+  else if (acc == protected_field && TYPE_FIELD_PROTECTED (type, index))
+    return 1;
+  else if (acc == public_field && !TYPE_FIELD_PRIVATE (type, index)
+	   && !TYPE_FIELD_PROTECTED (type, index))
+    return 1;
+  else
+    return 0;
+}
+
+static void
+cplus_describe_child (struct varobj *parent, int index,
+		      char **cname, struct value **cvalue, struct type **ctype,
+		      char **cfull_expression)
+{
+  struct value *value;
+  struct type *type;
+  int was_ptr;
+  int lookup_actual_type = 0;
+  char *parent_expression = NULL;
+  struct varobj *var;
+  struct value_print_options opts;
+
+  if (cname)
+    *cname = NULL;
+  if (cvalue)
+    *cvalue = NULL;
+  if (ctype)
+    *ctype = NULL;
+  if (cfull_expression)
+    *cfull_expression = NULL;
+
+  get_user_print_options (&opts);
+
+  var = (CPLUS_FAKE_CHILD (parent)) ? parent->parent : parent;
+  if (opts.objectprint)
+    lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
+			  || TYPE_CODE (var->type) == TYPE_CODE_PTR);
+  value = var->value;
+  type = varobj_get_value_type (var);
+  if (cfull_expression)
+    parent_expression
+      = varobj_get_path_expr (varobj_get_path_expr_parent (var));
+
+  adjust_value_for_child_access (&value, &type, &was_ptr, lookup_actual_type);
+
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+      || TYPE_CODE (type) == TYPE_CODE_UNION)
+    {
+      char *join = was_ptr ? "->" : ".";
+
+      if (CPLUS_FAKE_CHILD (parent))
+	{
+	  /* The fields of the class type are ordered as they
+	     appear in the class.  We are given an index for a
+	     particular access control type ("public","protected",
+	     or "private").  We must skip over fields that don't
+	     have the access control we are looking for to properly
+	     find the indexed field.  */
+	  int type_index = TYPE_N_BASECLASSES (type);
+	  enum accessibility acc = public_field;
+	  int vptr_fieldno;
+	  struct type *basetype = NULL;
+	  const char *field_name;
+
+	  vptr_fieldno = get_vptr_fieldno (type, &basetype);
+	  if (strcmp (parent->name, "private") == 0)
+	    acc = private_field;
+	  else if (strcmp (parent->name, "protected") == 0)
+	    acc = protected_field;
+
+	  while (index >= 0)
+	    {
+	      if ((type == basetype && type_index == vptr_fieldno)
+		  || TYPE_FIELD_ARTIFICIAL (type, type_index))
+		; /* ignore vptr */
+	      else if (match_accessibility (type, type_index, acc))
+		    --index;
+		  ++type_index;
+	    }
+	  --type_index;
+
+	  /* If the type is anonymous and the field has no name,
+	     set an appopriate name.  */
+	  field_name = TYPE_FIELD_NAME (type, type_index);
+	  if (field_name == NULL || *field_name == '\0')
+	    {
+	      if (cname)
+		{
+		  if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
+		      == TYPE_CODE_STRUCT)
+		    *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
+		  else if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
+			   == TYPE_CODE_UNION)
+		    *cname = xstrdup (ANONYMOUS_UNION_NAME);
+		}
+
+	      if (cfull_expression)
+		*cfull_expression = xstrdup ("");
+	    }
+	  else
+	    {
+	      if (cname)
+		*cname = xstrdup (TYPE_FIELD_NAME (type, type_index));
+
+	      if (cfull_expression)
+		*cfull_expression
+		  = xstrprintf ("((%s)%s%s)", parent_expression, join,
+				field_name);
+	    }
+
+	  if (cvalue && value)
+	    *cvalue = value_struct_element_index (value, type_index);
+
+	  if (ctype)
+	    *ctype = TYPE_FIELD_TYPE (type, type_index);
+	}
+      else if (index < TYPE_N_BASECLASSES (type))
+	{
+	  /* This is a baseclass.  */
+	  if (cname)
+	    *cname = xstrdup (TYPE_FIELD_NAME (type, index));
+
+	  if (cvalue && value)
+	    *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value);
+
+	  if (ctype)
+	    {
+	      *ctype = TYPE_FIELD_TYPE (type, index);
+	    }
+
+	  if (cfull_expression)
+	    {
+	      char *ptr = was_ptr ? "*" : "";
+
+	      /* Cast the parent to the base' type.  Note that in gdb,
+		 expression like 
+		         (Base1)d
+		 will create an lvalue, for all appearences, so we don't
+		 need to use more fancy:
+		         *(Base1*)(&d)
+		 construct.
+
+		 When we are in the scope of the base class or of one
+		 of its children, the type field name will be interpreted
+		 as a constructor, if it exists.  Therefore, we must
+		 indicate that the name is a class name by using the
+		 'class' keyword.  See PR mi/11912  */
+	      *cfull_expression = xstrprintf ("(%s(class %s%s) %s)", 
+					      ptr, 
+					      TYPE_FIELD_NAME (type, index),
+					      ptr,
+					      parent_expression);
+	    }
+	}
+      else
+	{
+	  char *access = NULL;
+	  int children[3];
+
+	  cplus_class_num_children (type, children);
+
+	  /* Everything beyond the baseclasses can
+	     only be "public", "private", or "protected"
+
+	     The special "fake" children are always output by varobj in
+	     this order.  So if INDEX == 2, it MUST be "protected".  */
+	  index -= TYPE_N_BASECLASSES (type);
+	  switch (index)
+	    {
+	    case 0:
+	      if (children[v_public] > 0)
+	 	access = "public";
+	      else if (children[v_private] > 0)
+	 	access = "private";
+	      else 
+	 	access = "protected";
+	      break;
+	    case 1:
+	      if (children[v_public] > 0)
+		{
+		  if (children[v_private] > 0)
+		    access = "private";
+		  else
+		    access = "protected";
+		}
+	      else if (children[v_private] > 0)
+	 	access = "protected";
+	      break;
+	    case 2:
+	      /* Must be protected.  */
+	      access = "protected";
+	      break;
+	    default:
+	      /* error!  */
+	      break;
+	    }
+
+	  gdb_assert (access);
+	  if (cname)
+	    *cname = xstrdup (access);
+
+	  /* Value and type and full expression are null here.  */
+	}
+    }
+  else
+    {
+      c_describe_child (parent, index, cname, cvalue, ctype, cfull_expression);
+    }  
+}
+
+static char *
+cplus_name_of_child (struct varobj *parent, int index)
+{
+  char *name = NULL;
+
+  cplus_describe_child (parent, index, &name, NULL, NULL, NULL);
+  return name;
+}
+
+static char *
+cplus_path_expr_of_child (struct varobj *child)
+{
+  cplus_describe_child (child->parent, child->index, NULL, NULL, NULL, 
+			&child->path_expr);
+  return child->path_expr;
+}
+
+static struct value *
+cplus_value_of_child (struct varobj *parent, int index)
+{
+  struct value *value = NULL;
+
+  cplus_describe_child (parent, index, NULL, &value, NULL, NULL);
+  return value;
+}
+
+static struct type *
+cplus_type_of_child (struct varobj *parent, int index)
+{
+  struct type *type = NULL;
+
+  cplus_describe_child (parent, index, NULL, NULL, &type, NULL);
+  return type;
+}
+
+static char *
+cplus_value_of_variable (struct varobj *var, 
+			 enum varobj_display_formats format)
+{
+
+  /* If we have one of our special types, don't print out
+     any value.  */
+  if (CPLUS_FAKE_CHILD (var))
+    return xstrdup ("");
+
+  return c_value_of_variable (var, format);
+}
+
+
+/* varobj operations for c++.  */
+
+const struct lang_varobj_ops cplus_varobj_ops =
+{
+   cplus_number_of_children,
+   cplus_name_of_variable,
+   cplus_name_of_child,
+   cplus_path_expr_of_child,
+   cplus_value_of_child,
+   cplus_type_of_child,
+   cplus_value_of_variable,
+   varobj_default_value_is_changeable_p,
+   NULL /* value_has_mutated */
+};
+
+
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 6c809a4..4da6ca2 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -239,6 +239,22 @@ get_type_arch (const struct type *type)
     return TYPE_OWNER (type).gdbarch;
 }
 
+/* This returns the target type (or NULL) of TYPE, also skipping
+   past typedefs.  */
+
+struct type *
+get_target_type (struct type *type)
+{
+  if (type != NULL)
+    {
+      type = TYPE_TARGET_TYPE (type);
+      if (type != NULL)
+	type = check_typedef (type);
+    }
+
+  return type;
+}
+
 /* Alloc a new type instance structure, fill it with some defaults,
    and point it at OLDTYPE.  Allocate the new type instance from the
    same place as OLDTYPE.  */
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 5e8d1e7..d7fdedf 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1431,6 +1431,10 @@ extern struct type *alloc_type_copy (const struct type *);
    objfile's architecture is returned.  */
 extern struct gdbarch *get_type_arch (const struct type *);
 
+/* This returns the target type (or NULL) of TYPE, also skipping
+   past typedefs.  */
+extern struct type *get_target_type (struct type *type);
+
 /* Helper function to construct objfile-owned types.  */
 extern struct type *init_type (enum type_code, int, int, const char *,
 			       struct objfile *);
diff --git a/gdb/jv-varobj.c b/gdb/jv-varobj.c
new file mode 100644
index 0000000..e70aa28
--- /dev/null
+++ b/gdb/jv-varobj.c
@@ -0,0 +1,105 @@
+/* varobj support for Java.
+
+   Copyright (C) 1999-2013 Free Software Foundation, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "varobj.h"
+
+/* Java */
+
+static int
+java_number_of_children (struct varobj *var)
+{
+  return cplus_varobj_ops.number_of_children (var);
+}
+
+static char *
+java_name_of_variable (struct varobj *parent)
+{
+  char *p, *name;
+
+  name = cplus_varobj_ops.name_of_variable (parent);
+  /* If  the name has "-" in it, it is because we
+     needed to escape periods in the name...  */
+  p = name;
+
+  while (*p != '\000')
+    {
+      if (*p == '-')
+	*p = '.';
+      p++;
+    }
+
+  return name;
+}
+
+static char *
+java_name_of_child (struct varobj *parent, int index)
+{
+  char *name, *p;
+
+  name = cplus_varobj_ops.name_of_child (parent, index);
+  /* Escape any periods in the name...  */
+  p = name;
+
+  while (*p != '\000')
+    {
+      if (*p == '.')
+	*p = '-';
+      p++;
+    }
+
+  return name;
+}
+
+static char *
+java_path_expr_of_child (struct varobj *child)
+{
+  return NULL;
+}
+
+static struct value *
+java_value_of_child (struct varobj *parent, int index)
+{
+  return cplus_varobj_ops.value_of_child (parent, index);
+}
+
+static struct type *
+java_type_of_child (struct varobj *parent, int index)
+{
+  return cplus_varobj_ops.type_of_child (parent, index);
+}
+
+static char *
+java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
+{
+  return cplus_varobj_ops.value_of_variable (var, format);
+}
+
+/* varobj operations for java.  */
+
+const struct lang_varobj_ops java_varobj_ops =
+{
+   java_number_of_children,
+   java_name_of_variable,
+   java_name_of_child,
+   java_path_expr_of_child,
+   java_value_of_child,
+   java_type_of_child,
+   java_value_of_variable,
+   varobj_default_value_is_changeable_p,
+   NULL /* value_has_mutated */
+};
diff --git a/gdb/varobj.c b/gdb/varobj.c
index b3ba56b..a215358 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -33,8 +33,6 @@
 #include "vec.h"
 #include "gdbthread.h"
 #include "inferior.h"
-#include "ada-varobj.h"
-#include "ada-lang.h"
 
 #if HAVE_PYTHON
 #include "python/python.h"
@@ -43,10 +41,6 @@
 typedef int PyObject;
 #endif
 
-/* The names of varobjs representing anonymous structs or unions.  */
-#define ANONYMOUS_STRUCT_NAME _("<anonymous struct>")
-#define ANONYMOUS_UNION_NAME _("<anonymous union>")
-
 /* Non-zero if we want to see trace of varobj level stuff.  */
 
 unsigned int varobjdebug = 0;
@@ -106,8 +100,9 @@ struct varobj_root
      to symbols that do not exist anymore.  */
   int is_valid;
 
-  /* Language info for this variable and its children.  */
-  struct language_specific *lang;
+  /* Language-related operations for this variable and its
+     children.  */
+  struct lang_varobj_ops *lang;
 
   /* The varobj for this root node.  */
   struct varobj *rootvar;
@@ -190,12 +185,6 @@ static void free_variable (struct varobj *var);
 
 static struct cleanup *make_cleanup_free_variable (struct varobj *var);
 
-static struct type *get_type (struct varobj *var);
-
-static struct type *get_value_type (struct varobj *var);
-
-static struct type *get_target_type (struct type *);
-
 static enum varobj_display_formats variable_default_display (struct varobj *);
 
 static void cppush (struct cpstack **pstack, char *name);
@@ -225,12 +214,6 @@ static struct value *value_of_child (struct varobj *parent, int index);
 static char *my_value_of_variable (struct varobj *var,
 				   enum varobj_display_formats format);
 
-static char *value_get_print_value (struct value *value,
-				    enum varobj_display_formats format,
-				    struct varobj *var);
-
-static int varobj_value_is_changeable_p (struct varobj *var);
-
 static int is_root_p (struct varobj *var);
 
 #if HAVE_PYTHON
@@ -241,190 +224,12 @@ static struct varobj *varobj_add_child (struct varobj *var,
 
 #endif /* HAVE_PYTHON */
 
-static int default_value_is_changeable_p (struct varobj *var);
-
-/* C implementation */
-
-static int c_number_of_children (struct varobj *var);
-
-static char *c_name_of_variable (struct varobj *parent);
-
-static char *c_name_of_child (struct varobj *parent, int index);
-
-static char *c_path_expr_of_child (struct varobj *child);
-
-static struct value *c_value_of_child (struct varobj *parent, int index);
-
-static struct type *c_type_of_child (struct varobj *parent, int index);
-
-static char *c_value_of_variable (struct varobj *var,
-				  enum varobj_display_formats format);
-
-/* C++ implementation */
-
-static int cplus_number_of_children (struct varobj *var);
-
-static void cplus_class_num_children (struct type *type, int children[3]);
-
-static char *cplus_name_of_variable (struct varobj *parent);
-
-static char *cplus_name_of_child (struct varobj *parent, int index);
-
-static char *cplus_path_expr_of_child (struct varobj *child);
-
-static struct value *cplus_value_of_child (struct varobj *parent, int index);
-
-static struct type *cplus_type_of_child (struct varobj *parent, int index);
-
-static char *cplus_value_of_variable (struct varobj *var,
-				      enum varobj_display_formats format);
-
-/* Java implementation */
-
-static int java_number_of_children (struct varobj *var);
-
-static char *java_name_of_variable (struct varobj *parent);
-
-static char *java_name_of_child (struct varobj *parent, int index);
-
-static char *java_path_expr_of_child (struct varobj *child);
-
-static struct value *java_value_of_child (struct varobj *parent, int index);
-
-static struct type *java_type_of_child (struct varobj *parent, int index);
-
-static char *java_value_of_variable (struct varobj *var,
-				     enum varobj_display_formats format);
-
-/* Ada implementation */
-
-static int ada_number_of_children (struct varobj *var);
-
-static char *ada_name_of_variable (struct varobj *parent);
-
-static char *ada_name_of_child (struct varobj *parent, int index);
-
-static char *ada_path_expr_of_child (struct varobj *child);
-
-static struct value *ada_value_of_child (struct varobj *parent, int index);
-
-static struct type *ada_type_of_child (struct varobj *parent, int index);
-
-static char *ada_value_of_variable (struct varobj *var,
-				    enum varobj_display_formats format);
-
-static int ada_value_is_changeable_p (struct varobj *var);
-
-static int ada_value_has_mutated (struct varobj *var, struct value *new_val,
-				  struct type *new_type);
-
-/* The language specific vector */
-
-struct language_specific
-{
-  /* The number of children of PARENT.  */
-  int (*number_of_children) (struct varobj * parent);
-
-  /* The name (expression) of a root varobj.  */
-  char *(*name_of_variable) (struct varobj * parent);
-
-  /* The name of the INDEX'th child of PARENT.  */
-  char *(*name_of_child) (struct varobj * parent, int index);
-
-  /* Returns the rooted expression of CHILD, which is a variable
-     obtain that has some parent.  */
-  char *(*path_expr_of_child) (struct varobj * child);
-
-  /* The ``struct value *'' of the INDEX'th child of PARENT.  */
-  struct value *(*value_of_child) (struct varobj * parent, int index);
-
-  /* The type of the INDEX'th child of PARENT.  */
-  struct type *(*type_of_child) (struct varobj * parent, int index);
-
-  /* The current value of VAR.  */
-  char *(*value_of_variable) (struct varobj * var,
-			      enum varobj_display_formats format);
-
-  /* Return non-zero if changes in value of VAR must be detected and
-     reported by -var-update.  Return zero if -var-update should never
-     report changes of such values.  This makes sense for structures
-     (since the changes in children values will be reported separately),
-     or for artifical objects (like 'public' pseudo-field in C++).
-
-     Return value of 0 means that gdb need not call value_fetch_lazy
-     for the value of this variable object.  */
-  int (*value_is_changeable_p) (struct varobj *var);
-
-  /* Return nonzero if the type of VAR has mutated.
-
-     VAR's value is still the varobj's previous value, while NEW_VALUE
-     is VAR's new value and NEW_TYPE is the var's new type.  NEW_VALUE
-     may be NULL indicating that there is no value available (the varobj
-     may be out of scope, of may be the child of a null pointer, for
-     instance).  NEW_TYPE, on the other hand, must never be NULL.
-
-     This function should also be able to assume that var's number of
-     children is set (not < 0).
-
-     Languages where types do not mutate can set this to NULL.  */
-  int (*value_has_mutated) (struct varobj *var, struct value *new_value,
-			    struct type *new_type);
-};
-
 /* Array of known source language routines.  */
-static struct language_specific languages[vlang_end] = {
-  /* C */
-  {
-   c_number_of_children,
-   c_name_of_variable,
-   c_name_of_child,
-   c_path_expr_of_child,
-   c_value_of_child,
-   c_type_of_child,
-   c_value_of_variable,
-   default_value_is_changeable_p,
-   NULL /* value_has_mutated */}
-  ,
-  /* C++ */
-  {
-   cplus_number_of_children,
-   cplus_name_of_variable,
-   cplus_name_of_child,
-   cplus_path_expr_of_child,
-   cplus_value_of_child,
-   cplus_type_of_child,
-   cplus_value_of_variable,
-   default_value_is_changeable_p,
-   NULL /* value_has_mutated */}
-  ,
-  /* Java */
-  {
-   java_number_of_children,
-   java_name_of_variable,
-   java_name_of_child,
-   java_path_expr_of_child,
-   java_value_of_child,
-   java_type_of_child,
-   java_value_of_variable,
-   default_value_is_changeable_p,
-   NULL /* value_has_mutated */},
-  /* Ada */
-  {
-   ada_number_of_children,
-   ada_name_of_variable,
-   ada_name_of_child,
-   ada_path_expr_of_child,
-   ada_value_of_child,
-   ada_type_of_child,
-   ada_value_of_variable,
-   ada_value_is_changeable_p,
-   ada_value_has_mutated}
-};
-
-/* A little convenience enum for dealing with C++/Java.  */
-enum vsections
-{
-  v_public = 0, v_private, v_protected
+static const struct lang_varobj_ops *languages[vlang_end] = {
+  &c_varobj_ops,
+  &cplus_varobj_ops,
+  &java_varobj_ops,
+  &ada_varobj_ops,
 };
 
 /* Private data */
@@ -442,9 +247,6 @@ static struct varobj_root *rootlist;
 /* Pointer to the varobj hash table (built at run time).  */
 static struct vlist **varobj_table;
 
-/* Is the variable X one of our "fake" children?  */
-#define CPLUS_FAKE_CHILD(x) \
-((x) != NULL && (x)->type == NULL && (x)->value == NULL)
 
 
 /* API Implementation */
@@ -632,7 +434,7 @@ varobj_create (char *objname,
 
       /* Set language info */
       lang = variable_language (var);
-      var->root->lang = &languages[lang];
+      var->root->lang = (struct lang_varobj_ops *) languages[lang];
 
       install_new_value (var, value, 1 /* Initial assignment */);
 
@@ -812,7 +614,8 @@ varobj_set_display_format (struct varobj *var,
       && var->value && !value_lazy (var->value))
     {
       xfree (var->print_value);
-      var->print_value = value_get_print_value (var->value, var->format, var);
+      var->print_value = varobj_value_get_print_value (var->value,
+						       var->format, var);
     }
 
   return var->format;
@@ -894,8 +697,8 @@ varobj_get_frozen (struct varobj *var)
    of FROM and TO -- if either is negative, the entire range is
    used.  */
 
-static void
-restrict_range (VEC (varobj_p) *children, int *from, int *to)
+void
+varobj_restrict_range (VEC (varobj_p) *children, int *from, int *to)
 {
   if (*from < 0 || *to < 0)
     {
@@ -1202,7 +1005,7 @@ varobj_list_children (struct varobj *var, int *from, int *to)
 	 varobj twice is not something a sane frontend would do.  */
       update_dynamic_varobj_children (var, NULL, NULL, NULL, NULL,
 				      &children_changed, 0, 0, *to);
-      restrict_range (var->children, from, to);
+      varobj_restrict_range (var->children, from, to);
       return var->children;
     }
 
@@ -1233,7 +1036,7 @@ varobj_list_children (struct varobj *var, int *from, int *to)
 	}
     }
 
-  restrict_range (var->children, from, to);
+  varobj_restrict_range (var->children, from, to);
   return var->children;
 }
 
@@ -1287,7 +1090,7 @@ is_path_expr_parent (struct varobj *var)
   if (CPLUS_FAKE_CHILD (var))
     return 0;
 
-  type = get_value_type (var);
+  type = varobj_get_value_type (var);
 
   /* Anonymous unions and structs are also not path_expr parents.  */
   return !((TYPE_CODE (type) == TYPE_CODE_STRUCT
@@ -1297,8 +1100,8 @@ is_path_expr_parent (struct varobj *var)
 
 /* Return the path expression parent for VAR.  */
 
-static struct varobj *
-get_path_expr_parent (struct varobj *var)
+struct varobj *
+varobj_get_path_expr_parent (struct varobj *var)
 {
   struct varobj *parent = var;
 
@@ -1692,7 +1495,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
      should not be fetched.  */
   if (value != NULL && !value_lazy (value)
       && var->dynamic->pretty_printer == NULL)
-    print_value = value_get_print_value (value, var->format, var);
+    print_value = varobj_value_get_print_value (value, var->format, var);
 
   /* If the type is changeable, compare the old and the new values.
      If this is the initial assignment, we don't have any old value
@@ -1766,7 +1569,8 @@ install_new_value (struct varobj *var, struct value *value, int initial)
   if (var->dynamic->pretty_printer != NULL)
     {
       xfree (print_value);
-      print_value = value_get_print_value (var->value, var->format, var);
+      print_value = varobj_value_get_print_value (var->value, var->format,
+						  var);
       if ((var->print_value == NULL && print_value != NULL)
 	  || (var->print_value != NULL && print_value == NULL)
 	  || (var->print_value != NULL && print_value != NULL
@@ -2313,20 +2117,6 @@ create_child (struct varobj *parent, int index, char *name)
 				  value_of_child (parent, index));
 }
 
-/* Does CHILD represent a child with no name?  This happens when
-   the child is an anonmous struct or union and it has no field name
-   in its parent variable.
-
-   This has already been determined by *_describe_child. The easiest
-   thing to do is to compare the child's name with ANONYMOUS_*_NAME.  */
-
-static int
-is_anonymous_child (struct varobj *child)
-{
-  return (strcmp (child->name, ANONYMOUS_STRUCT_NAME) == 0
-	  || strcmp (child->name, ANONYMOUS_UNION_NAME) == 0);
-}
-
 static struct varobj *
 create_child_with_value (struct varobj *parent, int index, char *name,
 			 struct value *value)
@@ -2342,7 +2132,7 @@ create_child_with_value (struct varobj *parent, int index, char *name,
   child->parent = parent;
   child->root = parent->root;
 
-  if (is_anonymous_child (child))
+  if (varobj_is_anonymous_child (child))
     childs_name = xstrprintf ("%s.%d_anonymous", parent->obj_name, index);
   else
     childs_name = xstrprintf ("%s.%s", parent->obj_name, name);
@@ -2469,23 +2259,6 @@ make_cleanup_free_variable (struct varobj *var)
   return make_cleanup (do_free_variable_cleanup, var);
 }
 
-/* This returns the type of the variable.  It also skips past typedefs
-   to return the real type of the variable.
-
-   NOTE: TYPE_TARGET_TYPE should NOT be used anywhere in this file
-   except within get_target_type and get_type.  */
-static struct type *
-get_type (struct varobj *var)
-{
-  struct type *type;
-
-  type = var->type;
-  if (type != NULL)
-    type = check_typedef (type);
-
-  return type;
-}
-
 /* Return the type of the value that's stored in VAR,
    or that would have being stored there if the
    value were accessible.
@@ -2497,8 +2270,8 @@ get_type (struct varobj *var)
    the values and for comparing previous and new values.
 
    For example, top-level references are always stripped.  */
-static struct type *
-get_value_type (struct varobj *var)
+struct type *
+varobj_get_value_type (struct varobj *var)
 {
   struct type *type;
 
@@ -2517,24 +2290,6 @@ get_value_type (struct varobj *var)
   return type;
 }
 
-/* This returns the target type (or NULL) of TYPE, also skipping
-   past typedefs, just like get_type ().
-
-   NOTE: TYPE_TARGET_TYPE should NOT be used anywhere in this file
-   except within get_target_type and get_type.  */
-static struct type *
-get_target_type (struct type *type)
-{
-  if (type != NULL)
-    {
-      type = TYPE_TARGET_TYPE (type);
-      if (type != NULL)
-	type = check_typedef (type);
-    }
-
-  return type;
-}
-
 /* What is the default display for this variable? We assume that
    everything is "natural".  Any exceptions?  */
 static enum varobj_display_formats
@@ -2828,16 +2583,26 @@ my_value_of_variable (struct varobj *var, enum varobj_display_formats format)
   if (var->root->is_valid)
     {
       if (var->dynamic->pretty_printer != NULL)
-	return value_get_print_value (var->value, var->format, var);
+	return varobj_value_get_print_value (var->value, var->format, var);
       return (*var->root->lang->value_of_variable) (var, format);
     }
   else
     return NULL;
 }
 
-static char *
-value_get_print_value (struct value *value, enum varobj_display_formats format,
-		       struct varobj *var)
+void
+varobj_formatted_print_options (struct value_print_options *opts,
+				enum varobj_display_formats format)
+{
+  get_formatted_print_options (opts, format_code[(int) format]);
+  opts->deref_ref = 0;
+  opts->raw = 1;
+}
+
+char *
+varobj_value_get_print_value (struct value *value,
+			      enum varobj_display_formats format,
+			      struct varobj *var)
 {
   struct ui_file *stb;
   struct cleanup *old_chain;
@@ -2948,9 +2713,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
     }
 #endif
 
-  get_formatted_print_options (&opts, format_code[(int) format]);
-  opts.deref_ref = 0;
-  opts.raw = 1;
+  varobj_formatted_print_options (&opts, format);
 
   /* If the THEVALUE has contents, it is a regular string.  */
   if (thevalue)
@@ -2977,7 +2740,7 @@ varobj_editable_p (struct varobj *var)
   if (!(var->root->is_valid && var->value && VALUE_LVAL (var->value)))
     return 0;
 
-  type = get_value_type (var);
+  type = varobj_get_value_type (var);
 
   switch (TYPE_CODE (type))
     {
@@ -2997,7 +2760,7 @@ varobj_editable_p (struct varobj *var)
 
 /* Call VAR's value_is_changeable_p language-specific callback.  */
 
-static int
+int
 varobj_value_is_changeable_p (struct varobj *var)
 {
   return var->root->lang->value_is_changeable_p (var);
@@ -3012,95 +2775,11 @@ varobj_floating_p (struct varobj *var)
   return var->root->floating;
 }
 
-/* Given the value and the type of a variable object,
-   adjust the value and type to those necessary
-   for getting children of the variable object.
-   This includes dereferencing top-level references
-   to all types and dereferencing pointers to
-   structures.
-
-   If LOOKUP_ACTUAL_TYPE is set the enclosing type of the
-   value will be fetched and if it differs from static type
-   the value will be casted to it.
-
-   Both TYPE and *TYPE should be non-null.  VALUE
-   can be null if we want to only translate type.
-   *VALUE can be null as well -- if the parent
-   value is not known.
-
-   If WAS_PTR is not NULL, set *WAS_PTR to 0 or 1
-   depending on whether pointer was dereferenced
-   in this function.  */
-static void
-adjust_value_for_child_access (struct value **value,
-				  struct type **type,
-				  int *was_ptr,
-				  int lookup_actual_type)
-{
-  gdb_assert (type && *type);
-
-  if (was_ptr)
-    *was_ptr = 0;
-
-  *type = check_typedef (*type);
-  
-  /* The type of value stored in varobj, that is passed
-     to us, is already supposed to be
-     reference-stripped.  */
-
-  gdb_assert (TYPE_CODE (*type) != TYPE_CODE_REF);
-
-  /* Pointers to structures are treated just like
-     structures when accessing children.  Don't
-     dererences pointers to other types.  */
-  if (TYPE_CODE (*type) == TYPE_CODE_PTR)
-    {
-      struct type *target_type = get_target_type (*type);
-      if (TYPE_CODE (target_type) == TYPE_CODE_STRUCT
-	  || TYPE_CODE (target_type) == TYPE_CODE_UNION)
-	{
-	  if (value && *value)
-	    {
-	      volatile struct gdb_exception except;
-
-	      TRY_CATCH (except, RETURN_MASK_ERROR)
-		{
-		  *value = value_ind (*value);
-		}
-
-	      if (except.reason < 0)
-		*value = NULL;
-	    }
-	  *type = target_type;
-	  if (was_ptr)
-	    *was_ptr = 1;
-	}
-    }
-
-  /* The 'get_target_type' function calls check_typedef on
-     result, so we can immediately check type code.  No
-     need to call check_typedef here.  */
-
-  /* Access a real type of the value (if necessary and possible).  */
-  if (value && *value && lookup_actual_type)
-    {
-      struct type *enclosing_type;
-      int real_type_found = 0;
-
-      enclosing_type = value_actual_type (*value, 1, &real_type_found);
-      if (real_type_found)
-        {
-          *type = enclosing_type;
-          *value = value_cast (enclosing_type, *value);
-        }
-    }
-}
-
 /* Implement the "value_is_changeable_p" varobj callback for most
    languages.  */
 
-static int
-default_value_is_changeable_p (struct varobj *var)
+int
+varobj_default_value_is_changeable_p (struct varobj *var)
 {
   int r;
   struct type *type;
@@ -3108,7 +2787,7 @@ default_value_is_changeable_p (struct varobj *var)
   if (CPLUS_FAKE_CHILD (var))
     return 0;
 
-  type = get_value_type (var);
+  type = varobj_get_value_type (var);
 
   switch (TYPE_CODE (type))
     {
@@ -3125,925 +2804,6 @@ default_value_is_changeable_p (struct varobj *var)
   return r;
 }
 
-/* C */
-
-static int
-c_number_of_children (struct varobj *var)
-{
-  struct type *type = get_value_type (var);
-  int children = 0;
-  struct type *target;
-
-  adjust_value_for_child_access (NULL, &type, NULL, 0);
-  target = get_target_type (type);
-
-  switch (TYPE_CODE (type))
-    {
-    case TYPE_CODE_ARRAY:
-      if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (target) > 0
-	  && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
-	children = TYPE_LENGTH (type) / TYPE_LENGTH (target);
-      else
-	/* If we don't know how many elements there are, don't display
-	   any.  */
-	children = 0;
-      break;
-
-    case TYPE_CODE_STRUCT:
-    case TYPE_CODE_UNION:
-      children = TYPE_NFIELDS (type);
-      break;
-
-    case TYPE_CODE_PTR:
-      /* The type here is a pointer to non-struct.  Typically, pointers
-	 have one child, except for function ptrs, which have no children,
-	 and except for void*, as we don't know what to show.
-
-         We can show char* so we allow it to be dereferenced.  If you decide
-         to test for it, please mind that a little magic is necessary to
-         properly identify it: char* has TYPE_CODE == TYPE_CODE_INT and 
-         TYPE_NAME == "char".  */
-      if (TYPE_CODE (target) == TYPE_CODE_FUNC
-	  || TYPE_CODE (target) == TYPE_CODE_VOID)
-	children = 0;
-      else
-	children = 1;
-      break;
-
-    default:
-      /* Other types have no children.  */
-      break;
-    }
-
-  return children;
-}
-
-static char *
-c_name_of_variable (struct varobj *parent)
-{
-  return xstrdup (parent->name);
-}
-
-/* Return the value of element TYPE_INDEX of a structure
-   value VALUE.  VALUE's type should be a structure,
-   or union, or a typedef to struct/union.
-
-   Returns NULL if getting the value fails.  Never throws.  */
-static struct value *
-value_struct_element_index (struct value *value, int type_index)
-{
-  struct value *result = NULL;
-  volatile struct gdb_exception e;
-  struct type *type = value_type (value);
-
-  type = check_typedef (type);
-
-  gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
-	      || TYPE_CODE (type) == TYPE_CODE_UNION);
-
-  TRY_CATCH (e, RETURN_MASK_ERROR)
-    {
-      if (field_is_static (&TYPE_FIELD (type, type_index)))
-	result = value_static_field (type, type_index);
-      else
-	result = value_primitive_field (value, 0, type_index, type);
-    }
-  if (e.reason < 0)
-    {
-      return NULL;
-    }
-  else
-    {
-      return result;
-    }
-}
-
-/* Obtain the information about child INDEX of the variable
-   object PARENT.
-   If CNAME is not null, sets *CNAME to the name of the child relative
-   to the parent.
-   If CVALUE is not null, sets *CVALUE to the value of the child.
-   If CTYPE is not null, sets *CTYPE to the type of the child.
-
-   If any of CNAME, CVALUE, or CTYPE is not null, but the corresponding
-   information cannot be determined, set *CNAME, *CVALUE, or *CTYPE
-   to NULL.  */
-static void 
-c_describe_child (struct varobj *parent, int index,
-		  char **cname, struct value **cvalue, struct type **ctype,
-		  char **cfull_expression)
-{
-  struct value *value = parent->value;
-  struct type *type = get_value_type (parent);
-  char *parent_expression = NULL;
-  int was_ptr;
-  volatile struct gdb_exception except;
-
-  if (cname)
-    *cname = NULL;
-  if (cvalue)
-    *cvalue = NULL;
-  if (ctype)
-    *ctype = NULL;
-  if (cfull_expression)
-    {
-      *cfull_expression = NULL;
-      parent_expression = varobj_get_path_expr (get_path_expr_parent (parent));
-    }
-  adjust_value_for_child_access (&value, &type, &was_ptr, 0);
-      
-  switch (TYPE_CODE (type))
-    {
-    case TYPE_CODE_ARRAY:
-      if (cname)
-	*cname
-	  = xstrdup (int_string (index 
-				 + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
-				 10, 1, 0, 0));
-
-      if (cvalue && value)
-	{
-	  int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
-
-	  TRY_CATCH (except, RETURN_MASK_ERROR)
-	    {
-	      *cvalue = value_subscript (value, real_index);
-	    }
-	}
-
-      if (ctype)
-	*ctype = get_target_type (type);
-
-      if (cfull_expression)
-	*cfull_expression = 
-	  xstrprintf ("(%s)[%s]", parent_expression, 
-		      int_string (index
-				  + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
-				  10, 1, 0, 0));
-
-
-      break;
-
-    case TYPE_CODE_STRUCT:
-    case TYPE_CODE_UNION:
-      {
-	const char *field_name;
-
-	/* If the type is anonymous and the field has no name,
-	   set an appropriate name.  */
-	field_name = TYPE_FIELD_NAME (type, index);
-	if (field_name == NULL || *field_name == '\0')
-	  {
-	    if (cname)
-	      {
-		if (TYPE_CODE (TYPE_FIELD_TYPE (type, index))
-		    == TYPE_CODE_STRUCT)
-		  *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
-		else
-		  *cname = xstrdup (ANONYMOUS_UNION_NAME);
-	      }
-
-	    if (cfull_expression)
-	      *cfull_expression = xstrdup ("");
-	  }
-	else
-	  {
-	    if (cname)
-	      *cname = xstrdup (field_name);
-
-	    if (cfull_expression)
-	      {
-		char *join = was_ptr ? "->" : ".";
-
-		*cfull_expression = xstrprintf ("(%s)%s%s", parent_expression,
-						join, field_name);
-	      }
-	  }
-
-	if (cvalue && value)
-	  {
-	    /* For C, varobj index is the same as type index.  */
-	    *cvalue = value_struct_element_index (value, index);
-	  }
-
-	if (ctype)
-	  *ctype = TYPE_FIELD_TYPE (type, index);
-      }
-      break;
-
-    case TYPE_CODE_PTR:
-      if (cname)
-	*cname = xstrprintf ("*%s", parent->name);
-
-      if (cvalue && value)
-	{
-	  TRY_CATCH (except, RETURN_MASK_ERROR)
-	    {
-	      *cvalue = value_ind (value);
-	    }
-
-	  if (except.reason < 0)
-	    *cvalue = NULL;
-	}
-
-      /* Don't use get_target_type because it calls
-	 check_typedef and here, we want to show the true
-	 declared type of the variable.  */
-      if (ctype)
-	*ctype = TYPE_TARGET_TYPE (type);
-
-      if (cfull_expression)
-	*cfull_expression = xstrprintf ("*(%s)", parent_expression);
-      
-      break;
-
-    default:
-      /* This should not happen.  */
-      if (cname)
-	*cname = xstrdup ("???");
-      if (cfull_expression)
-	*cfull_expression = xstrdup ("???");
-      /* Don't set value and type, we don't know then.  */
-    }
-}
-
-static char *
-c_name_of_child (struct varobj *parent, int index)
-{
-  char *name;
-
-  c_describe_child (parent, index, &name, NULL, NULL, NULL);
-  return name;
-}
-
-static char *
-c_path_expr_of_child (struct varobj *child)
-{
-  c_describe_child (child->parent, child->index, NULL, NULL, NULL, 
-		    &child->path_expr);
-  return child->path_expr;
-}
-
-static struct value *
-c_value_of_child (struct varobj *parent, int index)
-{
-  struct value *value = NULL;
-
-  c_describe_child (parent, index, NULL, &value, NULL, NULL);
-  return value;
-}
-
-static struct type *
-c_type_of_child (struct varobj *parent, int index)
-{
-  struct type *type = NULL;
-
-  c_describe_child (parent, index, NULL, NULL, &type, NULL);
-  return type;
-}
-
-static char *
-c_value_of_variable (struct varobj *var, enum varobj_display_formats format)
-{
-  /* BOGUS: if val_print sees a struct/class, or a reference to one,
-     it will print out its children instead of "{...}".  So we need to
-     catch that case explicitly.  */
-  struct type *type = get_type (var);
-
-  /* Strip top-level references.  */
-  while (TYPE_CODE (type) == TYPE_CODE_REF)
-    type = check_typedef (TYPE_TARGET_TYPE (type));
-
-  switch (TYPE_CODE (type))
-    {
-    case TYPE_CODE_STRUCT:
-    case TYPE_CODE_UNION:
-      return xstrdup ("{...}");
-      /* break; */
-
-    case TYPE_CODE_ARRAY:
-      {
-	char *number;
-
-	number = xstrprintf ("[%d]", var->num_children);
-	return (number);
-      }
-      /* break; */
-
-    default:
-      {
-	if (var->value == NULL)
-	  {
-	    /* This can happen if we attempt to get the value of a struct
-	       member when the parent is an invalid pointer.  This is an
-	       error condition, so we should tell the caller.  */
-	    return NULL;
-	  }
-	else
-	  {
-	    if (var->not_fetched && value_lazy (var->value))
-	      /* Frozen variable and no value yet.  We don't
-		 implicitly fetch the value.  MI response will
-		 use empty string for the value, which is OK.  */
-	      return NULL;
-
-	    gdb_assert (varobj_value_is_changeable_p (var));
-	    gdb_assert (!value_lazy (var->value));
-	    
-	    /* If the specified format is the current one,
-	       we can reuse print_value.  */
-	    if (format == var->format)
-	      return xstrdup (var->print_value);
-	    else
-	      return value_get_print_value (var->value, format, var);
-	  }
-      }
-    }
-}
-
-
-/* C++ */
-
-static int
-cplus_number_of_children (struct varobj *var)
-{
-  struct value *value = NULL;
-  struct type *type;
-  int children, dont_know;
-  int lookup_actual_type = 0;
-  struct value_print_options opts;
-
-  dont_know = 1;
-  children = 0;
-
-  get_user_print_options (&opts);
-
-  if (!CPLUS_FAKE_CHILD (var))
-    {
-      type = get_value_type (var);
-
-      /* It is necessary to access a real type (via RTTI).  */
-      if (opts.objectprint)
-        {
-          value = var->value;
-          lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
-				|| TYPE_CODE (var->type) == TYPE_CODE_PTR);
-        }
-      adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
-
-      if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
-	  ((TYPE_CODE (type)) == TYPE_CODE_UNION))
-	{
-	  int kids[3];
-
-	  cplus_class_num_children (type, kids);
-	  if (kids[v_public] != 0)
-	    children++;
-	  if (kids[v_private] != 0)
-	    children++;
-	  if (kids[v_protected] != 0)
-	    children++;
-
-	  /* Add any baseclasses.  */
-	  children += TYPE_N_BASECLASSES (type);
-	  dont_know = 0;
-
-	  /* FIXME: save children in var.  */
-	}
-    }
-  else
-    {
-      int kids[3];
-
-      type = get_value_type (var->parent);
-
-      /* It is necessary to access a real type (via RTTI).  */
-      if (opts.objectprint)
-        {
-	  struct varobj *parent = var->parent;
-
-	  value = parent->value;
-	  lookup_actual_type = (TYPE_CODE (parent->type) == TYPE_CODE_REF
-				|| TYPE_CODE (parent->type) == TYPE_CODE_PTR);
-        }
-      adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
-
-      cplus_class_num_children (type, kids);
-      if (strcmp (var->name, "public") == 0)
-	children = kids[v_public];
-      else if (strcmp (var->name, "private") == 0)
-	children = kids[v_private];
-      else
-	children = kids[v_protected];
-      dont_know = 0;
-    }
-
-  if (dont_know)
-    children = c_number_of_children (var);
-
-  return children;
-}
-
-/* Compute # of public, private, and protected variables in this class.
-   That means we need to descend into all baseclasses and find out
-   how many are there, too.  */
-static void
-cplus_class_num_children (struct type *type, int children[3])
-{
-  int i, vptr_fieldno;
-  struct type *basetype = NULL;
-
-  children[v_public] = 0;
-  children[v_private] = 0;
-  children[v_protected] = 0;
-
-  vptr_fieldno = get_vptr_fieldno (type, &basetype);
-  for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
-    {
-      /* If we have a virtual table pointer, omit it.  Even if virtual
-	 table pointers are not specifically marked in the debug info,
-	 they should be artificial.  */
-      if ((type == basetype && i == vptr_fieldno)
-	  || TYPE_FIELD_ARTIFICIAL (type, i))
-	continue;
-
-      if (TYPE_FIELD_PROTECTED (type, i))
-	children[v_protected]++;
-      else if (TYPE_FIELD_PRIVATE (type, i))
-	children[v_private]++;
-      else
-	children[v_public]++;
-    }
-}
-
-static char *
-cplus_name_of_variable (struct varobj *parent)
-{
-  return c_name_of_variable (parent);
-}
-
-enum accessibility { private_field, protected_field, public_field };
-
-/* Check if field INDEX of TYPE has the specified accessibility.
-   Return 0 if so and 1 otherwise.  */
-static int 
-match_accessibility (struct type *type, int index, enum accessibility acc)
-{
-  if (acc == private_field && TYPE_FIELD_PRIVATE (type, index))
-    return 1;
-  else if (acc == protected_field && TYPE_FIELD_PROTECTED (type, index))
-    return 1;
-  else if (acc == public_field && !TYPE_FIELD_PRIVATE (type, index)
-	   && !TYPE_FIELD_PROTECTED (type, index))
-    return 1;
-  else
-    return 0;
-}
-
-static void
-cplus_describe_child (struct varobj *parent, int index,
-		      char **cname, struct value **cvalue, struct type **ctype,
-		      char **cfull_expression)
-{
-  struct value *value;
-  struct type *type;
-  int was_ptr;
-  int lookup_actual_type = 0;
-  char *parent_expression = NULL;
-  struct varobj *var;
-  struct value_print_options opts;
-
-  if (cname)
-    *cname = NULL;
-  if (cvalue)
-    *cvalue = NULL;
-  if (ctype)
-    *ctype = NULL;
-  if (cfull_expression)
-    *cfull_expression = NULL;
-
-  get_user_print_options (&opts);
-
-  var = (CPLUS_FAKE_CHILD (parent)) ? parent->parent : parent;
-  if (opts.objectprint)
-    lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
-			  || TYPE_CODE (var->type) == TYPE_CODE_PTR);
-  value = var->value;
-  type = get_value_type (var);
-  if (cfull_expression)
-    parent_expression = varobj_get_path_expr (get_path_expr_parent (var));
-
-  adjust_value_for_child_access (&value, &type, &was_ptr, lookup_actual_type);
-
-  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-      || TYPE_CODE (type) == TYPE_CODE_UNION)
-    {
-      char *join = was_ptr ? "->" : ".";
-
-      if (CPLUS_FAKE_CHILD (parent))
-	{
-	  /* The fields of the class type are ordered as they
-	     appear in the class.  We are given an index for a
-	     particular access control type ("public","protected",
-	     or "private").  We must skip over fields that don't
-	     have the access control we are looking for to properly
-	     find the indexed field.  */
-	  int type_index = TYPE_N_BASECLASSES (type);
-	  enum accessibility acc = public_field;
-	  int vptr_fieldno;
-	  struct type *basetype = NULL;
-	  const char *field_name;
-
-	  vptr_fieldno = get_vptr_fieldno (type, &basetype);
-	  if (strcmp (parent->name, "private") == 0)
-	    acc = private_field;
-	  else if (strcmp (parent->name, "protected") == 0)
-	    acc = protected_field;
-
-	  while (index >= 0)
-	    {
-	      if ((type == basetype && type_index == vptr_fieldno)
-		  || TYPE_FIELD_ARTIFICIAL (type, type_index))
-		; /* ignore vptr */
-	      else if (match_accessibility (type, type_index, acc))
-		    --index;
-		  ++type_index;
-	    }
-	  --type_index;
-
-	  /* If the type is anonymous and the field has no name,
-	     set an appopriate name.  */
-	  field_name = TYPE_FIELD_NAME (type, type_index);
-	  if (field_name == NULL || *field_name == '\0')
-	    {
-	      if (cname)
-		{
-		  if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
-		      == TYPE_CODE_STRUCT)
-		    *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
-		  else if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
-			   == TYPE_CODE_UNION)
-		    *cname = xstrdup (ANONYMOUS_UNION_NAME);
-		}
-
-	      if (cfull_expression)
-		*cfull_expression = xstrdup ("");
-	    }
-	  else
-	    {
-	      if (cname)
-		*cname = xstrdup (TYPE_FIELD_NAME (type, type_index));
-
-	      if (cfull_expression)
-		*cfull_expression
-		  = xstrprintf ("((%s)%s%s)", parent_expression, join,
-				field_name);
-	    }
-
-	  if (cvalue && value)
-	    *cvalue = value_struct_element_index (value, type_index);
-
-	  if (ctype)
-	    *ctype = TYPE_FIELD_TYPE (type, type_index);
-	}
-      else if (index < TYPE_N_BASECLASSES (type))
-	{
-	  /* This is a baseclass.  */
-	  if (cname)
-	    *cname = xstrdup (TYPE_FIELD_NAME (type, index));
-
-	  if (cvalue && value)
-	    *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value);
-
-	  if (ctype)
-	    {
-	      *ctype = TYPE_FIELD_TYPE (type, index);
-	    }
-
-	  if (cfull_expression)
-	    {
-	      char *ptr = was_ptr ? "*" : "";
-
-	      /* Cast the parent to the base' type.  Note that in gdb,
-		 expression like 
-		         (Base1)d
-		 will create an lvalue, for all appearences, so we don't
-		 need to use more fancy:
-		         *(Base1*)(&d)
-		 construct.
-
-		 When we are in the scope of the base class or of one
-		 of its children, the type field name will be interpreted
-		 as a constructor, if it exists.  Therefore, we must
-		 indicate that the name is a class name by using the
-		 'class' keyword.  See PR mi/11912  */
-	      *cfull_expression = xstrprintf ("(%s(class %s%s) %s)", 
-					      ptr, 
-					      TYPE_FIELD_NAME (type, index),
-					      ptr,
-					      parent_expression);
-	    }
-	}
-      else
-	{
-	  char *access = NULL;
-	  int children[3];
-
-	  cplus_class_num_children (type, children);
-
-	  /* Everything beyond the baseclasses can
-	     only be "public", "private", or "protected"
-
-	     The special "fake" children are always output by varobj in
-	     this order.  So if INDEX == 2, it MUST be "protected".  */
-	  index -= TYPE_N_BASECLASSES (type);
-	  switch (index)
-	    {
-	    case 0:
-	      if (children[v_public] > 0)
-	 	access = "public";
-	      else if (children[v_private] > 0)
-	 	access = "private";
-	      else 
-	 	access = "protected";
-	      break;
-	    case 1:
-	      if (children[v_public] > 0)
-		{
-		  if (children[v_private] > 0)
-		    access = "private";
-		  else
-		    access = "protected";
-		}
-	      else if (children[v_private] > 0)
-	 	access = "protected";
-	      break;
-	    case 2:
-	      /* Must be protected.  */
-	      access = "protected";
-	      break;
-	    default:
-	      /* error!  */
-	      break;
-	    }
-
-	  gdb_assert (access);
-	  if (cname)
-	    *cname = xstrdup (access);
-
-	  /* Value and type and full expression are null here.  */
-	}
-    }
-  else
-    {
-      c_describe_child (parent, index, cname, cvalue, ctype, cfull_expression);
-    }  
-}
-
-static char *
-cplus_name_of_child (struct varobj *parent, int index)
-{
-  char *name = NULL;
-
-  cplus_describe_child (parent, index, &name, NULL, NULL, NULL);
-  return name;
-}
-
-static char *
-cplus_path_expr_of_child (struct varobj *child)
-{
-  cplus_describe_child (child->parent, child->index, NULL, NULL, NULL, 
-			&child->path_expr);
-  return child->path_expr;
-}
-
-static struct value *
-cplus_value_of_child (struct varobj *parent, int index)
-{
-  struct value *value = NULL;
-
-  cplus_describe_child (parent, index, NULL, &value, NULL, NULL);
-  return value;
-}
-
-static struct type *
-cplus_type_of_child (struct varobj *parent, int index)
-{
-  struct type *type = NULL;
-
-  cplus_describe_child (parent, index, NULL, NULL, &type, NULL);
-  return type;
-}
-
-static char *
-cplus_value_of_variable (struct varobj *var, 
-			 enum varobj_display_formats format)
-{
-
-  /* If we have one of our special types, don't print out
-     any value.  */
-  if (CPLUS_FAKE_CHILD (var))
-    return xstrdup ("");
-
-  return c_value_of_variable (var, format);
-}
-
-/* Java */
-
-static int
-java_number_of_children (struct varobj *var)
-{
-  return cplus_number_of_children (var);
-}
-
-static char *
-java_name_of_variable (struct varobj *parent)
-{
-  char *p, *name;
-
-  name = cplus_name_of_variable (parent);
-  /* If  the name has "-" in it, it is because we
-     needed to escape periods in the name...  */
-  p = name;
-
-  while (*p != '\000')
-    {
-      if (*p == '-')
-	*p = '.';
-      p++;
-    }
-
-  return name;
-}
-
-static char *
-java_name_of_child (struct varobj *parent, int index)
-{
-  char *name, *p;
-
-  name = cplus_name_of_child (parent, index);
-  /* Escape any periods in the name...  */
-  p = name;
-
-  while (*p != '\000')
-    {
-      if (*p == '.')
-	*p = '-';
-      p++;
-    }
-
-  return name;
-}
-
-static char *
-java_path_expr_of_child (struct varobj *child)
-{
-  return NULL;
-}
-
-static struct value *
-java_value_of_child (struct varobj *parent, int index)
-{
-  return cplus_value_of_child (parent, index);
-}
-
-static struct type *
-java_type_of_child (struct varobj *parent, int index)
-{
-  return cplus_type_of_child (parent, index);
-}
-
-static char *
-java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
-{
-  return cplus_value_of_variable (var, format);
-}
-
-/* Ada specific callbacks for VAROBJs.  */
-
-static int
-ada_number_of_children (struct varobj *var)
-{
-  return ada_varobj_get_number_of_children (var->value, var->type);
-}
-
-static char *
-ada_name_of_variable (struct varobj *parent)
-{
-  return c_name_of_variable (parent);
-}
-
-static char *
-ada_name_of_child (struct varobj *parent, int index)
-{
-  return ada_varobj_get_name_of_child (parent->value, parent->type,
-				       parent->name, index);
-}
-
-static char*
-ada_path_expr_of_child (struct varobj *child)
-{
-  struct varobj *parent = child->parent;
-  const char *parent_path_expr = varobj_get_path_expr (parent);
-
-  return ada_varobj_get_path_expr_of_child (parent->value,
-					    parent->type,
-					    parent->name,
-					    parent_path_expr,
-					    child->index);
-}
-
-static struct value *
-ada_value_of_child (struct varobj *parent, int index)
-{
-  return ada_varobj_get_value_of_child (parent->value, parent->type,
-					parent->name, index);
-}
-
-static struct type *
-ada_type_of_child (struct varobj *parent, int index)
-{
-  return ada_varobj_get_type_of_child (parent->value, parent->type,
-				       index);
-}
-
-static char *
-ada_value_of_variable (struct varobj *var, enum varobj_display_formats format)
-{
-  struct value_print_options opts;
-
-  get_formatted_print_options (&opts, format_code[(int) format]);
-  opts.deref_ref = 0;
-  opts.raw = 1;
-
-  return ada_varobj_get_value_of_variable (var->value, var->type, &opts);
-}
-
-/* Implement the "value_is_changeable_p" routine for Ada.  */
-
-static int
-ada_value_is_changeable_p (struct varobj *var)
-{
-  struct type *type = var->value ? value_type (var->value) : var->type;
-
-  if (ada_is_array_descriptor_type (type)
-      && TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
-    {
-      /* This is in reality a pointer to an unconstrained array.
-	 its value is changeable.  */
-      return 1;
-    }
-
-  if (ada_is_string_type (type))
-    {
-      /* We display the contents of the string in the array's
-	 "value" field.  The contents can change, so consider
-	 that the array is changeable.  */
-      return 1;
-    }
-
-  return default_value_is_changeable_p (var);
-}
-
-/* Implement the "value_has_mutated" routine for Ada.  */
-
-static int
-ada_value_has_mutated (struct varobj *var, struct value *new_val,
-		       struct type *new_type)
-{
-  int i;
-  int from = -1;
-  int to = -1;
-
-  /* If the number of fields have changed, then for sure the type
-     has mutated.  */
-  if (ada_varobj_get_number_of_children (new_val, new_type)
-      != var->num_children)
-    return 1;
-
-  /* If the number of fields have remained the same, then we need
-     to check the name of each field.  If they remain the same,
-     then chances are the type hasn't mutated.  This is technically
-     an incomplete test, as the child's type might have changed
-     despite the fact that the name remains the same.  But we'll
-     handle this situation by saying that the child has mutated,
-     not this value.
-
-     If only part (or none!) of the children have been fetched,
-     then only check the ones we fetched.  It does not matter
-     to the frontend whether a child that it has not fetched yet
-     has mutated or not. So just assume it hasn't.  */
-
-  restrict_range (var->children, &from, &to);
-  for (i = from; i < to; i++)
-    if (strcmp (ada_varobj_get_name_of_child (new_val, new_type,
-					      var->name, i),
-		VEC_index (varobj_p, var->children, i)->name) != 0)
-      return 1;
-
-  return 0;
-}
-
 /* Iterate all the existing _root_ VAROBJs and call the FUNC callback for them
    with an arbitrary caller supplied DATA pointer.  */
 
diff --git a/gdb/varobj.h b/gdb/varobj.h
index ea6e09b..c8ba0ad 100644
--- a/gdb/varobj.h
+++ b/gdb/varobj.h
@@ -167,6 +167,68 @@ struct varobj
   struct varobj_dynamic *dynamic;
 };
 
+/* Is the variable X one of our "fake" children?  */
+#define CPLUS_FAKE_CHILD(x) \
+((x) != NULL && (x)->type == NULL && (x)->value == NULL)
+
+/* The language specific vector */
+
+struct lang_varobj_ops
+{
+  /* The number of children of PARENT.  */
+  int (*number_of_children) (struct varobj * parent);
+
+  /* The name (expression) of a root varobj.  */
+  char *(*name_of_variable) (struct varobj * parent);
+
+  /* The name of the INDEX'th child of PARENT.  */
+  char *(*name_of_child) (struct varobj * parent, int index);
+
+  /* Returns the rooted expression of CHILD, which is a variable
+     obtain that has some parent.  */
+  char *(*path_expr_of_child) (struct varobj * child);
+
+  /* The ``struct value *'' of the INDEX'th child of PARENT.  */
+  struct value *(*value_of_child) (struct varobj * parent, int index);
+
+  /* The type of the INDEX'th child of PARENT.  */
+  struct type *(*type_of_child) (struct varobj * parent, int index);
+
+  /* The current value of VAR.  */
+  char *(*value_of_variable) (struct varobj * var,
+			      enum varobj_display_formats format);
+
+  /* Return non-zero if changes in value of VAR must be detected and
+     reported by -var-update.  Return zero if -var-update should never
+     report changes of such values.  This makes sense for structures
+     (since the changes in children values will be reported separately),
+     or for artifical objects (like 'public' pseudo-field in C++).
+
+     Return value of 0 means that gdb need not call value_fetch_lazy
+     for the value of this variable object.  */
+  int (*value_is_changeable_p) (struct varobj *var);
+
+  /* Return nonzero if the type of VAR has mutated.
+
+     VAR's value is still the varobj's previous value, while NEW_VALUE
+     is VAR's new value and NEW_TYPE is the var's new type.  NEW_VALUE
+     may be NULL indicating that there is no value available (the varobj
+     may be out of scope, of may be the child of a null pointer, for
+     instance).  NEW_TYPE, on the other hand, must never be NULL.
+
+     This function should also be able to assume that var's number of
+     children is set (not < 0).
+
+     Languages where types do not mutate can set this to NULL.  */
+  int (*value_has_mutated) (struct varobj *var, struct value *new_value,
+			    struct type *new_type);
+};
+
+const struct lang_varobj_ops c_varobj_ops;
+const struct lang_varobj_ops cplus_varobj_ops;
+const struct lang_varobj_ops java_varobj_ops;
+const struct lang_varobj_ops ada_varobj_ops;
+
 /* API functions */
 
 extern struct varobj *varobj_create (char *objname,
@@ -254,4 +316,22 @@ extern int varobj_has_more (struct varobj *var, int to);
 
 extern int varobj_pretty_printed_p (struct varobj *var);
 
+extern int varobj_default_value_is_changeable_p (struct varobj *var);
+extern int varobj_value_is_changeable_p (struct varobj *var);
+
+extern struct type *varobj_get_value_type (struct varobj *var);
+
+extern int varobj_is_anonymous_child (struct varobj *child);
+
+extern struct varobj *varobj_get_path_expr_parent (struct varobj *var);
+
+extern char *varobj_value_get_print_value (struct value *value,
+					   enum varobj_display_formats format,
+					   struct varobj *var);
+
+extern void varobj_formatted_print_options (struct value_print_options *opts,
+					    enum varobj_display_formats format);
+
+extern void varobj_restrict_range (VEC (varobj_p) *children, int *from,
+				   int *to);
 #endif /* VAROBJ_H */
-- 
1.7.7.6


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]