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]

[rfa] expose gdb values to python, mark II


Hi folks,

This is the latest version of the patch. The documentation part remains the
same which Eli approved before.

There are two differences in this one: it always uses current_gdbarch to get
the appropriate types when it needs to create values, and it has support
for pointer arithmetic in valpy_binop.

Ok?
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
2008-10-30  Thiago Jung Bauermann  <bauerman@br.ibm.com>
	    Tom Tromey  <tromey@redhat.com>

gdb/
	* Makefile.in (SUBDIR_PYTHON_OBS): Add python-value.o.
	(SUBDIR_PYTHON_SRCS): Add python-value.c.
	(python-value.o): New target.
	* configure.ac (CONFIG_OBS): Add python-value.o.
	(CONFIG_SRCS): Add python/python-value.c
	* configure: Regenerate.
	* python-internal.h (value_object_type): Add external declaration.
	(gdbpy_get_value_from_history, value_to_value_object,
	convert_value_from_python, gdbpy_initialize_values): Add function
	prototype.
	* python/python-value.c: New file.
	* python/python.c (GdbMethods): Add gdbpy_get_value_from_history.
	(_initialize_python): Call gdbpy_initialize_values.
	* python/python.h (values_in_python): Add external declaration.
	* value.c (value_prepend_to_list, value_remove_from_list): New
	functions.
	(preserve_values): Iterate over values_in_python list as well.
	* value.h (value_prepend_to_list, value_remove_from_list): Add
	function prototypes.

gdb/doc/
	* gdb.texinfo. (Values From Inferior): New subsubsection.

gdb/testsuite/
	* gdb.python/python-value.c: New file.
	* gdb.python/python-value.exp: New file.

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 2cd5596..fdaafca 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -271,10 +271,12 @@ SUBDIR_TUI_CFLAGS= \
 #
 SUBDIR_PYTHON_OBS = \
 	python.o \
-	python-utils.o
+	python-utils.o \
+	python-value.o
 SUBDIR_PYTHON_SRCS = \
 	python/python.c \
-	python/python-utils.c
+	python/python-utils.c \
+	python/python-value.c
 SUBDIR_PYTHON_DEPS =
 SUBDIR_PYTHON_LDFLAGS=
 SUBDIR_PYTHON_CFLAGS=
@@ -1849,6 +1851,10 @@ python-utils.o: $(srcdir)/python/python-utils.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-utils.c
 	$(POSTCOMPILE)
 
+python-value.o: $(srcdir)/python/python-value.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-value.c
+	$(POSTCOMPILE)
+
 #
 # Dependency tracking.  Most of this is conditional on GNU Make being
 # found by configure; if GNU Make is not found, we fall back to a
diff --git a/gdb/configure b/gdb/configure
index 7955569..7f4d2a6 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -11704,10 +11704,10 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 echo "${ECHO_T}${PYTHON_CFLAGS}" >&6
   fi
 else
-  # Even if Python support is not compiled in, we need to have this file
+  # Even if Python support is not compiled in, we need to have these files
   # included in order to recognize the GDB command "python".
-  CONFIG_OBS="$CONFIG_OBS python.o"
-  CONFIG_SRCS="$CONFIG_SRCS python/python.c"
+  CONFIG_OBS="$CONFIG_OBS python.o python-value.o"
+  CONFIG_SRCS="$CONFIG_SRCS python/python.c python/python-value.c"
 fi
 
 
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 680fba0..677a6ae 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -624,10 +624,10 @@ if test "${have_libpython}" = yes; then
     AC_MSG_RESULT(${PYTHON_CFLAGS})
   fi
 else
-  # Even if Python support is not compiled in, we need to have this file
+  # Even if Python support is not compiled in, we need to have these files
   # included in order to recognize the GDB command "python".
-  CONFIG_OBS="$CONFIG_OBS python.o"
-  CONFIG_SRCS="$CONFIG_SRCS python/python.c"
+  CONFIG_OBS="$CONFIG_OBS python.o python-value.o"
+  CONFIG_SRCS="$CONFIG_SRCS python/python.c python/python-value.c"
 fi
 AC_SUBST(PYTHON_CFLAGS)
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9db0ff8..a22b41e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -17674,6 +17674,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
 @menu
 * Basic Python::                Basic Python Functions.
 * Exception Handling::
+* Values From Inferior::
 @end menu
 
 @node Basic Python
@@ -17752,6 +17753,64 @@ message as its value, and the Python call stack backtrace at the
 Python statement closest to where the @value{GDBN} error occured as the
 traceback.
 
+@node Values From Inferior
+@subsubsection Values From Inferior
+@cindex values from inferior, with Python
+@cindex python, working with values from inferior
+
+@cindex @code{gdb.Value}
+@value{GDBN} provides values it obtains from the inferior program in
+an object of type @code{gdb.Value}.  @value{GDBN} uses this object
+for its internal bookkeeping of the inferior's values, and for
+fetching values when necessary.
+
+Inferior values that are simple scalars can be used directly in
+Python expressions that are valid for the value's data type  Here's
+an example for an integer or floating-point value @code{some_val}:
+
+@smallexample
+bar = some_val + 2
+@end smallexample
+
+@noindent
+As result of this, @code{bar} will also be a @code{gdb.Value} object
+whose values are of the same type as those of @code{some_val}.
+
+Inferior values that are structures or instances of some class can
+be accessed using the Python @dfn{dictionary syntax}.  For example, if
+@code{some_val} is a @code{gdb.Value} instance holding a structure, you
+can access its @code{foo} element with:
+
+@smallexample
+bar = some_val['foo']
+@end smallexample
+
+Again, @code{bar} will also be a @code{gdb.Value} object.
+
+For pointer data types, @code{gdb.Value} provides a method for
+dereferencing the pointer to obtain the object it points to.
+
+@defmethod Value dereference
+This method returns a new @code{gdb.Value} object whose contents is
+the object pointed to by the pointer.  For example, if @code{foo} is
+a C pointer to an @code{int}, declared in your C program as
+
+@smallexample
+int *foo;
+@end smallexample
+
+@noindent
+then you can use the corresponding @code{gdb.Value} to access what
+@code{foo} points to like this:
+
+@smallexample
+bar = foo.dereference ()
+@end smallexample
+
+The result @code{bar} will be a @code{gdb.Value} object holding the
+value pointed to by @code{foo}.
+@end defmethod
+
 @node Interpreters
 @chapter Command Interpreters
 @cindex command interpreters
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index f850448..72f7a5f 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -43,11 +43,18 @@ typedef Py_intptr_t Py_ssize_t;
 #error "Unable to find usable Python.h"
 #endif
 
-struct block;
-struct symbol;
-struct symtab_and_line;
+struct value;
 
 extern PyObject *gdb_module;
+extern PyTypeObject value_object_type;
+
+PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
+
+PyObject *value_to_value_object (struct value *v);
+
+struct value *convert_value_from_python (PyObject *obj);
+
+void gdbpy_initialize_values (void);
 
 struct cleanup *make_cleanup_py_decref (PyObject *py);
 
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
new file mode 100644
index 0000000..cd80054
--- /dev/null
+++ b/gdb/python/python-value.c
@@ -0,0 +1,722 @@
+/* Python interface to values.
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "charset.h"
+#include "value.h"
+#include "exceptions.h"
+#include "language.h"
+#include "dfp.h"
+
+/* List of all values which are currently exposed to Python. It is
+   maintained so that when an objfile is discarded, preserve_values
+   can copy the values' types if needed.  This is declared
+   unconditionally to reduce the number of uses of HAVE_PYTHON in the
+   generic code.  */
+struct value *values_in_python;
+
+#ifdef HAVE_PYTHON
+
+#include "python-internal.h"
+
+/* Even though Python scalar types directly map to host types, we use
+   target types here to remain consistent with the the values system in
+   GDB (which uses target arithmetic).  */
+
+/* Python's integer type corresponds to C's long type.  */
+#define builtin_type_pyint builtin_type (current_gdbarch)->builtin_long
+
+/* Python's float type corresponds to C's double type.  */
+#define builtin_type_pyfloat builtin_type (current_gdbarch)->builtin_double
+
+/* Python's long type corresponds to C's long long type.  */
+#define builtin_type_pylong builtin_type (current_gdbarch)->builtin_long_long
+
+#define builtin_type_pybool \
+  language_bool_type (current_language, current_gdbarch)
+
+typedef struct {
+  PyObject_HEAD
+  struct value *value;
+  int owned_by_gdb;
+} value_object;
+
+static void valpy_dealloc (PyObject *obj);
+static PyObject *valpy_new (PyTypeObject *subtype, PyObject *args,
+			    PyObject *keywords);
+static Py_ssize_t valpy_length (PyObject *self);
+static PyObject *valpy_getitem (PyObject *self, PyObject *key);
+static int valpy_setitem (PyObject *self, PyObject *key, PyObject *value);
+static PyObject *valpy_str (PyObject *self);
+static PyObject *valpy_add (PyObject *self, PyObject *other);
+static PyObject *valpy_subtract (PyObject *self, PyObject *other);
+static PyObject *valpy_multiply (PyObject *self, PyObject *other);
+static PyObject *valpy_divide (PyObject *self, PyObject *other);
+static PyObject *valpy_remainder (PyObject *self, PyObject *other);
+static PyObject *valpy_power (PyObject *self, PyObject *other, PyObject *unused);
+static PyObject *valpy_negative (PyObject *self);
+static PyObject *valpy_positive (PyObject *self);
+static PyObject *valpy_absolute (PyObject *self);
+static int valpy_nonzero (PyObject *self);
+static PyObject *valpy_richcompare (PyObject *self, PyObject *other, int op);
+static PyObject *valpy_dereference (PyObject *self, PyObject *args);
+
+static PyMethodDef value_object_methods[] = {
+  { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
+  {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods value_object_as_number = {
+  valpy_add,
+  valpy_subtract,
+  valpy_multiply,
+  valpy_divide,
+  valpy_remainder,
+  NULL,			      /* nb_divmod */
+  valpy_power,		      /* nb_power */
+  valpy_negative,	      /* nb_negative */
+  valpy_positive,	      /* nb_positive */
+  valpy_absolute,	      /* nb_absolute */
+  valpy_nonzero		      /* nb_nonzero */
+};
+
+static PyMappingMethods value_object_as_mapping = {
+  valpy_length,
+  valpy_getitem,
+  valpy_setitem
+};
+
+PyTypeObject value_object_type = {
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Value",			  /*tp_name*/
+  sizeof (value_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  valpy_dealloc,		  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  &value_object_as_number,	  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  &value_object_as_mapping,	  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  valpy_str,			  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,	/*tp_flags*/
+  "GDB value object",		  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  valpy_richcompare,		  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  value_object_methods		  /* tp_methods */
+};
+
+
+/* Called by the Python interpreter when deallocating a value object.  */
+static void
+valpy_dealloc (PyObject *obj)
+{
+  value_object *self = (value_object *) obj;
+
+  value_remove_from_list (&values_in_python, self->value);
+
+  if (!self->owned_by_gdb)
+    value_free (self->value);
+  self->ob_type->tp_free (self);
+}
+
+/* Called when a new gdb.Value object needs to be allocated.  */
+static PyObject *
+valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
+{
+  struct value *value = NULL;   /* Initialize to appease gcc warning.  */
+  value_object *value_obj;
+  volatile struct gdb_exception except;
+
+  if (PyTuple_Size (args) != 1)
+    {
+      PyErr_SetString (PyExc_TypeError, _("Value object creation takes only "
+					  "1 argument"));
+      return NULL;
+    }
+
+  value_obj = (value_object *) subtype->tp_alloc (subtype, 1);
+  if (value_obj == NULL)
+    {
+      PyErr_SetString (PyExc_MemoryError, _("Could not allocate memory to "
+					    "create Value object."));
+      return NULL;
+    }
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      value = convert_value_from_python (PyTuple_GetItem (args, 0));
+    }
+  if (except.reason < 0)
+    {
+      subtype->tp_free (value_obj);
+      return PyErr_Format (except.reason == RETURN_QUIT
+			     ? PyExc_KeyboardInterrupt : PyExc_TypeError,
+			     "%s", except.message);
+    }
+
+  value_obj->value = value;
+  release_value (value);
+  value_prepend_to_list (&values_in_python, value);
+
+  return (PyObject *) value_obj;
+}
+
+/* Given a value of a pointer type, apply the C unary * operator to it.  */
+static PyObject *
+valpy_dereference (PyObject *self, PyObject *args)
+{
+  struct value *res_val = NULL;	  /* Initialize to appease gcc warning.  */
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      res_val = value_ind (((value_object *) self)->value);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return value_to_value_object (res_val);
+}
+
+static Py_ssize_t
+valpy_length (PyObject *self)
+{
+  /* We don't support getting the number of elements in a struct / class.  */
+  PyErr_SetString (PyExc_NotImplementedError,
+		   "Invalid operation on gdb.Value.");
+  return -1;
+}
+
+/* Given string name of an element inside structure, return its value
+   object.  */
+static PyObject *
+valpy_getitem (PyObject *self, PyObject *key)
+{
+  value_object *self_value = (value_object *) self;
+  char *field;
+  struct value *res_val = NULL;	  /* Initialize to appease gcc warning.  */
+  struct cleanup *old;
+  volatile struct gdb_exception except;
+
+  field = python_string_to_target_string (key);
+  if (field == NULL)
+    return NULL;
+
+  old = make_cleanup (xfree, field);
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      res_val = value_struct_elt (&self_value->value, NULL, field, 0, NULL);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  do_cleanups (old);
+
+  return value_to_value_object (res_val);
+}
+
+static int
+valpy_setitem (PyObject *self, PyObject *key, PyObject *value)
+{
+  PyErr_Format (PyExc_NotImplementedError,
+		_("Setting of struct elements is not currently supported."));
+  return -1;
+}
+
+/* Called by the Python interpreter to obtain string representation
+   of the object.  */
+static PyObject *
+valpy_str (PyObject *self)
+{
+  char *s = NULL;
+  long dummy;
+  struct ui_file *stb;
+  struct cleanup *old_chain;
+  PyObject *result;
+  volatile struct gdb_exception except;
+
+  stb = mem_fileopen ();
+  old_chain = make_cleanup_ui_file_delete (stb);
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      common_val_print (((value_object *) self)->value, stb, 0, 0, 0,
+			Val_pretty_default, current_language);
+      s = ui_file_xstrdup (stb, &dummy);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  do_cleanups (old_chain);
+
+  result = PyUnicode_Decode (s, strlen (s), host_charset (), NULL);
+  xfree (s);
+
+  return result;
+}
+
+enum valpy_opcode
+{
+  VALPY_ADD,
+  VALPY_SUB,
+  VALPY_MUL,
+  VALPY_DIV,
+  VALPY_REM,
+  VALPY_POW
+};
+
+/* If TYPE is a reference, return the target; otherwise return TYPE.  */
+#define STRIP_REFERENCE(TYPE) \
+  ((TYPE_CODE (TYPE) == TYPE_CODE_REF) ? (TYPE_TARGET_TYPE (TYPE)) : (TYPE))
+
+/* Returns a value object which is the sum of this value with the given
+   integer argument.  */
+static PyObject *
+valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
+{
+  long l;
+  double d;
+  struct value *res_val = NULL;	  /* Initialize to appease gcc warning.  */
+  struct value *other_val;
+  value_object *self_value;
+  volatile struct gdb_exception except;
+
+  /* If the gdb.Value object is the second operand, then it will be passed
+     to us as the OTHER argument, and SELF will be an entirely different
+     kind of object, altogether.  Swap them to avoid surprises.  */
+  if (!PyObject_TypeCheck (self, &value_object_type))
+    {
+      PyObject *tmp;
+
+      tmp = self;
+      self = other;
+      other = tmp;
+    }
+
+  self_value = (value_object *) self;
+
+  if (PyObject_TypeCheck (other, &value_object_type))
+    other_val = ((value_object *) other)->value;
+  else if (PyInt_Check (other))
+    {
+      l = PyInt_AsLong (other);
+      if (PyErr_Occurred ())
+	return Py_NotImplemented;
+
+      other_val = value_from_longest (builtin_type_pyint, l);
+    }
+  else if (PyFloat_Check (other))
+    {
+      d = PyFloat_AsDouble (other);
+      if (PyErr_Occurred ())
+	return Py_NotImplemented;
+
+      other_val = value_from_double (builtin_type_pyfloat, d);
+    }
+  else
+    /* If the types cannot be added, Python documentation says to return
+       NotImplemented (http://docs.python.org/ref/numeric-types.html).  */
+    return Py_NotImplemented;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      switch (opcode)
+	{
+	case VALPY_ADD:
+	  {
+	    struct type *ltype = value_type (self_value->value);
+	    struct type *rtype = value_type (other_val);
+	    CHECK_TYPEDEF (ltype);
+	    ltype = STRIP_REFERENCE (ltype);
+	    CHECK_TYPEDEF (rtype);
+	    rtype = STRIP_REFERENCE (rtype);
+
+	    if (TYPE_CODE (ltype) == TYPE_CODE_PTR)
+	      res_val = value_ptradd (self_value->value, other_val);
+	    else if (TYPE_CODE (rtype) == TYPE_CODE_PTR)
+	      res_val = value_ptradd (other_val, self_value->value);
+	    else
+	      res_val = value_binop (self_value->value, other_val, BINOP_ADD);
+	  }
+	  break;
+	case VALPY_SUB:
+	  {
+	    struct type *ltype = value_type (self_value->value);
+	    struct type *rtype = value_type (other_val);
+	    CHECK_TYPEDEF (ltype);
+	    ltype = STRIP_REFERENCE (ltype);
+	    CHECK_TYPEDEF (rtype);
+	    rtype = STRIP_REFERENCE (rtype);
+	    if (TYPE_CODE (ltype) == TYPE_CODE_PTR)
+	      {
+		if (TYPE_CODE (rtype) == TYPE_CODE_PTR)
+		  {
+		    /* A ptrdiff_t for the target would be preferable
+		       here.  */
+		    res_val
+		      = value_from_longest (builtin_type_pyint,
+					    value_ptrdiff (self_value->value,
+							   other_val));
+		  }
+		else
+		  res_val = value_ptrsub (self_value->value, other_val);
+	      }
+	    else
+	      res_val = value_binop (self_value->value, other_val, BINOP_SUB);
+	  }
+	  break;
+	case VALPY_MUL:
+	  res_val = value_binop (self_value->value, other_val, BINOP_MUL);
+	  break;
+	case VALPY_DIV:
+	  res_val = value_binop (self_value->value, other_val, BINOP_DIV);
+	  break;
+	case VALPY_REM:
+	  res_val = value_binop (self_value->value, other_val, BINOP_REM);
+	  break;
+	case VALPY_POW:
+	  res_val = value_binop (self_value->value, other_val, BINOP_EXP);
+	  break;
+	}
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return value_to_value_object (res_val);
+}
+
+static PyObject *
+valpy_add (PyObject *self, PyObject *other)
+{
+  return valpy_binop (VALPY_ADD, self, other);
+}
+
+static PyObject *
+valpy_subtract (PyObject *self, PyObject *other)
+{
+  return valpy_binop (VALPY_SUB, self, other);
+}
+
+static PyObject *
+valpy_multiply (PyObject *self, PyObject *other)
+{
+  return valpy_binop (VALPY_MUL, self, other);
+}
+
+static PyObject *
+valpy_divide (PyObject *self, PyObject *other)
+{
+  return valpy_binop (VALPY_DIV, self, other);
+}
+
+static PyObject *
+valpy_remainder (PyObject *self, PyObject *other)
+{
+  return valpy_binop (VALPY_REM, self, other);
+}
+
+static PyObject *
+valpy_power (PyObject *self, PyObject *other, PyObject *unused)
+{
+  /* We don't support the ternary form of pow.  I don't know how to express
+     that, so let's just throw NotImplementedError to at least do something
+     about it.  */
+  if (unused != Py_None)
+    {
+      PyErr_SetString (PyExc_NotImplementedError,
+		       "Invalid operation on gdb.Value.");
+      return NULL;
+    }
+
+  return valpy_binop (VALPY_POW, self, other);
+}
+
+static PyObject *
+valpy_negative (PyObject *self)
+{
+  struct value *val = NULL;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      val = value_neg (((value_object *) self)->value);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return value_to_value_object (val);
+}
+
+static PyObject *
+valpy_positive (PyObject *self)
+{
+  struct value *copy = value_copy (((value_object *) self)->value);
+
+  return value_to_value_object (copy);
+}
+
+static PyObject *
+valpy_absolute (PyObject *self)
+{
+  if (value_less (((value_object *) self)->value,
+		  value_from_longest (builtin_type_int8, 0)))
+    return valpy_negative (self);
+  else
+    return valpy_positive (self);
+}
+
+/* Implements boolean evaluation of gdb.Value.  */
+static int
+valpy_nonzero (PyObject *self)
+{
+  value_object *self_value = (value_object *) self;
+  struct type *type;
+
+  type = check_typedef (value_type (self_value->value));
+
+  if (is_integral_type (type) || TYPE_CODE (type) == TYPE_CODE_PTR)
+    return !!value_as_long (self_value->value);
+  else if (TYPE_CODE (type) == TYPE_CODE_FLT)
+    return value_as_double (self_value->value) != 0;
+  else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+    return !decimal_is_zero (value_contents (self_value->value),
+			     TYPE_LENGTH (type));
+  else
+    {
+      PyErr_SetString (PyExc_TypeError, _("Attempted truth testing on invalid "
+					  "gdb.Value type."));
+      return 0;
+    }
+}
+
+/* Implements comparison operations for value objects.  */
+static PyObject *
+valpy_richcompare (PyObject *self, PyObject *other, int op)
+{
+  int result = 0;
+  struct value *value_self, *value_other;
+  volatile struct gdb_exception except;
+
+  if (PyObject_TypeCheck (other, &value_object_type))
+    value_other = ((value_object *) other)->value;
+  else if (PyInt_Check (other))
+    {
+      LONGEST l;
+
+      l = PyInt_AsLong (other);
+      if (PyErr_Occurred ())
+	return NULL;
+
+      value_other = value_from_longest (builtin_type_pyint, l);
+    }
+  else if (PyFloat_Check (other))
+    {
+      DOUBLEST d;
+
+      d = PyFloat_AsDouble (other);
+      if (PyErr_Occurred ())
+	return NULL;
+
+      value_other = value_from_double (builtin_type_pyfloat, d);
+    }
+  else if (PyString_Check (other) || PyUnicode_Check (other))
+    {
+      char *str;
+
+      str = python_string_to_target_string (other);
+      value_other = value_from_string (str);
+      xfree (str);
+    }
+  else if (other == Py_None)
+    /* Comparing with None is special.  From what I can tell, in Python
+       None is smaller than anything else.  */
+    switch (op) {
+      case Py_LT:
+      case Py_LE:
+      case Py_EQ:
+	Py_RETURN_FALSE;
+      case Py_NE:
+      case Py_GT:
+      case Py_GE:
+	Py_RETURN_TRUE;
+      default:
+	/* Can't happen.  */
+	PyErr_SetString (PyExc_NotImplementedError,
+			 "Invalid operation on gdb.Value.");
+	return NULL;
+    }
+  else
+    {
+      PyErr_SetString (PyExc_NotImplementedError,
+		       "Operation not supported on gdb.Value of this type.");
+      return NULL;
+    }
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      switch (op) {
+        case Py_LT:
+	  result = value_less (((value_object *) self)->value, value_other);
+	  break;
+	case Py_LE:
+	  result = value_less (((value_object *) self)->value, value_other)
+	    || value_equal (((value_object *) self)->value, value_other);
+	  break;
+	case Py_EQ:
+	  result = value_equal (((value_object *) self)->value, value_other);
+	  break;
+	case Py_NE:
+	  result = !value_equal (((value_object *) self)->value, value_other);
+	  break;
+        case Py_GT:
+	  result = value_less (value_other, ((value_object *) self)->value);
+	  break;
+	case Py_GE:
+	  result = value_less (value_other, ((value_object *) self)->value)
+	    || value_equal (((value_object *) self)->value, value_other);
+	  break;
+	default:
+	  /* Can't happen.  */
+	  PyErr_SetString (PyExc_NotImplementedError,
+			   "Invalid operation on gdb.Value.");
+	  return NULL;
+      }
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (result == 1)
+    Py_RETURN_TRUE;
+
+  Py_RETURN_FALSE;
+}
+
+/* Returns an object for a value which is released from the all_values chain,
+   so its lifetime is not bound to the execution of a command.  */
+PyObject *
+value_to_value_object (struct value *val)
+{
+  value_object *val_obj;
+
+  val_obj = PyObject_New (value_object, &value_object_type);
+  if (val_obj != NULL)
+    {
+      val_obj->value = val;
+      release_value (val);
+      value_prepend_to_list (&values_in_python, val);
+    }
+
+  return (PyObject *) val_obj;
+}
+
+/* Try to convert a Python value to a gdb value.  If the value cannot
+   be converted, throw a gdb exception.  */
+
+struct value *
+convert_value_from_python (PyObject *obj)
+{
+  struct value *value = NULL; /* -Wall */
+  PyObject *target_str, *unicode_str;
+  struct cleanup *old;
+
+  if (! obj)
+    error (_("Internal error while converting Python value."));
+
+  if (PyBool_Check (obj))
+    value = value_from_longest (builtin_type_pybool, obj == Py_True);
+  else if (PyInt_Check (obj))
+    value = value_from_longest (builtin_type_pyint, PyInt_AsLong (obj));
+  else if (PyLong_Check (obj))
+    {
+      LONGEST l = PyLong_AsLongLong (obj);
+      if (! PyErr_Occurred ())
+	value = value_from_longest (builtin_type_pylong, l);
+    }
+  else if (PyFloat_Check (obj))
+    {
+      double d = PyFloat_AsDouble (obj);
+      if (! PyErr_Occurred ())
+	value = value_from_double (builtin_type_pyfloat, d);
+    }
+  else if (PyString_Check (obj) || PyUnicode_Check (obj))
+    {
+      char *s;
+
+      s = python_string_to_target_string (obj);
+      if (s == NULL)
+	return NULL;
+
+      old = make_cleanup (xfree, s);
+      value = value_from_string (s);
+      do_cleanups (old);
+    }
+  else if (PyObject_TypeCheck (obj, &value_object_type))
+    value = ((value_object *) obj)->value;
+  else
+    error (_("Could not convert Python object: %s"),
+	   PyString_AsString (PyObject_Str (obj)));
+
+  if (PyErr_Occurred ())
+    error (_("Error converting Python value."));
+
+  return value;
+}
+
+/* Returns value object in the ARGth position in GDB's history.  */
+PyObject *
+gdbpy_get_value_from_history (PyObject *self, PyObject *args)
+{
+  int i;
+  struct value *res_val = NULL;	  /* Initialize to appease gcc warning.  */
+  volatile struct gdb_exception except;
+
+  if (!PyArg_ParseTuple (args, "i", &i))
+    return NULL;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      res_val = access_value_history (i);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return value_to_value_object (res_val);
+}
+
+void
+gdbpy_initialize_values (void)
+{
+  value_object_type.tp_new = valpy_new;
+  if (PyType_Ready (&value_object_type) < 0)
+    return;
+
+  Py_INCREF (&value_object_type);
+  PyModule_AddObject (gdb_module, "Value", (PyObject *) &value_object_type);
+
+  values_in_python = NULL;
+}
+
+#endif /* HAVE_PYTHON */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 8bc24c2..77d8774 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -52,6 +52,8 @@ static PyObject *gdbpy_flush (PyObject *, PyObject *);
 
 static PyMethodDef GdbMethods[] =
 {
+  { "get_value_from_history", gdbpy_get_value_from_history, METH_VARARGS,
+    "Get a value from history" },
   { "execute", execute_gdb_command, METH_VARARGS,
     "Execute a gdb command" },
   { "get_parameter", get_parameter, METH_VARARGS,
@@ -398,6 +400,8 @@ Enables or disables printing of Python stack traces."),
   PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
   PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
 
+  gdbpy_initialize_values ();
+
   PyRun_SimpleString ("import gdb");
 
   /* Create a couple objects which are used for Python's stdout and
diff --git a/gdb/python/python.h b/gdb/python/python.h
index 00ff159..102fef6 100644
--- a/gdb/python/python.h
+++ b/gdb/python/python.h
@@ -22,6 +22,8 @@
 
 #include "value.h"
 
+extern struct value *values_in_python;
+
 void eval_python_from_control_command (struct command_line *);
 
 #endif /* GDB_PYTHON_H */
diff --git a/gdb/testsuite/gdb.python/python-value.c b/gdb/testsuite/gdb.python/python-value.c
new file mode 100644
index 0000000..82cfd9a
--- /dev/null
+++ b/gdb/testsuite/gdb.python/python-value.c
@@ -0,0 +1,41 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2008 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/>.  */
+
+struct s
+{
+  int a;
+  int b;
+};
+
+union u
+{
+  int a;
+  float b;
+};
+
+int
+main (int argc, char *argv[])
+{
+  struct s s;
+  union u u;
+
+  s.a = 3;
+  s.b = 5;
+  u.a = 7;
+
+  return 0;      /* break to inspect struct and union */
+}
diff --git a/gdb/testsuite/gdb.python/python-value.exp b/gdb/testsuite/gdb.python/python-value.exp
new file mode 100644
index 0000000..b723b9d
--- /dev/null
+++ b/gdb/testsuite/gdb.python/python-value.exp
@@ -0,0 +1,250 @@
+# Copyright (C) 2008 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/>.
+
+# This file is part of the GDB testsuite.  It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set testfile "python-value"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+    global gdb_prompt
+    foreach {input result} $args {
+	if {[gdb_test_multiple $input "$name - $input" {
+	    -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+		pass "$name - $input"
+	    }
+	}]} {
+	    return 1
+	}
+    }
+    return 0
+}
+
+# Run a command in GDB, and report a failure if a Python exception is thrown.
+# If report_pass is true, report a pass if no exception is thrown.
+proc gdb_py_test_silent_cmd {cmd name report_pass} {
+  global gdb_prompt
+
+  gdb_test_multiple $cmd $name {
+      -re "Traceback.*$gdb_prompt $"  { fail $name }
+      -re "$gdb_prompt $"	      { if $report_pass { pass $name } }
+  }
+}
+
+proc test_value_creation {} {
+  global gdb_prompt
+
+  gdb_py_test_silent_cmd "python i = gdb.Value (True)" "create boolean value" 1
+  gdb_py_test_silent_cmd "python i = gdb.Value (5)" "create integer value" 1
+  gdb_py_test_silent_cmd "python i = gdb.Value (5L)" "create long value" 1
+  gdb_py_test_silent_cmd "python f = gdb.Value (1.25)" "create double value" 1
+  gdb_py_test_silent_cmd "python a = gdb.Value ('string test')" "create 8-bit string value" 1
+  gdb_test "python print a" "\"string test\"" "print 8-bit string"
+  gdb_test "python print a.__class__" "<type 'gdb.Value'>" "verify type of 8-bit string"
+  gdb_py_test_silent_cmd "python a = gdb.Value (u'unicode test')" "create unicode value" 1
+  gdb_test "python print a" "\"unicode test\"" "print Unicode string"
+  gdb_test "python print a.__class__" "<type 'gdb.Value'>" "verify type of unicode string"
+}
+
+proc test_value_numeric_ops {} {
+  global gdb_prompt
+
+  gdb_py_test_silent_cmd "python i = gdb.Value (5)" "create first integer value" 0
+  gdb_py_test_silent_cmd "python j = gdb.Value (2)" "create second integer value" 0
+  gdb_py_test_silent_cmd "python f = gdb.Value (1.25)" "create first double value" 0
+  gdb_py_test_silent_cmd "python g = gdb.Value (2.5)" "create second double value" 0
+  gdb_test "python print 'result = ' + str(i+j)" " = 7" "add two integer values"
+  gdb_test "python print (i+j).__class__" "<type 'gdb.Value'>" "verify type of integer add result"
+
+  gdb_test "python print 'result = ' + str(f+g)" " = 3.75" "add two double values"
+  gdb_test "python print 'result = ' + str(i-j)" " = 3" "subtract two integer values"
+  gdb_test "python print 'result = ' + str(f-g)" " = -1.25" "subtract two double values"
+  gdb_test "python print 'result = ' + str(i*j)" " = 10" "multiply two integer values"
+  gdb_test "python print 'result = ' + str(f*g)" " = 3.125" "multiply two double values"
+  gdb_test "python print 'result = ' + str(i/j)" " = 2" "divide two integer values"
+  gdb_test "python print 'result = ' + str(f/g)" " = 0.5" "divide two double values"
+  gdb_test "python print 'result = ' + str(i%j)" " = 1" "take remainder of two integer values"
+  # Remainder of float is implemented in Python but not in GDB's value system.
+
+  gdb_test "python print 'result = ' + str(i**j)" " = 25" "integer value raised to the power of another integer value"
+  gdb_test "python print 'result = ' + str(g**j)" " = 6.25" "double value raised to the power of integer value"
+
+  gdb_test "python print 'result = ' + str(-i)" " = -5" "negated integer value"
+  gdb_test "python print 'result = ' + str(+i)" " = 5" "positive integer value"
+  gdb_test "python print 'result = ' + str(-f)" " = -1.25" "negated double value"
+  gdb_test "python print 'result = ' + str(+f)" " = 1.25" "positive double value"
+  gdb_test "python print 'result = ' + str(abs(j-i))" " = 3" "absolute of integer value"
+  gdb_test "python print 'result = ' + str(abs(f-g))" " = 1.25" "absolute of double value"
+
+  # Test gdb.Value mixed with Python types.
+
+  gdb_test "python print 'result = ' + str(i+1)" " = 6" "add integer value with python integer"
+  gdb_test "python print (i+1).__class__" "<type 'gdb.Value'>" "verify type of mixed integer add result"
+  gdb_test "python print 'result = ' + str(f+1.5)" " = 2.75" "add double value with python float"
+
+  gdb_test "python print 'result = ' + str(1+i)" " = 6" "add python integer with integer value"
+  gdb_test "python print 'result = ' + str(1.5+f)" " = 2.75" "add python float with double value"
+
+  # Test pointer arithmethic
+
+  # First, obtain the pointers
+  gdb_test "print (void *) 2" "" ""
+  gdb_test "python a = gdb.get_value_from_history (0)" "" ""
+  gdb_test "print (void *) 5" "" ""
+  gdb_test "python b = gdb.get_value_from_history (0)" "" ""
+
+  gdb_test "python print 'result = ' + str(a+5)" " = 0x7" "add pointer value with python integer"
+  gdb_test "python print 'result = ' + str(b-2)" " = 0x3" "subtract python integer from pointer value"
+  gdb_test "python print 'result = ' + str(b-a)" " = 3" "subtract two pointer values"
+
+  # Test some invalid operations.
+
+  gdb_test_multiple "python print 'result = ' + str(i+'foo')" "catch error in python type conversion" {
+      -re "unsupported operand type.*$gdb_prompt $"   {pass "catch error in python type conversion"}
+      -re "result = .*$gdb_prompt $"		      {fail "catch error in python type conversion"}
+      -re "$gdb_prompt $"			      {fail "catch error in python type conversion"}
+  }
+
+  gdb_test_multiple "python print 'result = ' + str(i+gdb.Value('foo'))" "catch throw of GDB error" {
+      -re "Traceback.*$gdb_prompt $"  {pass "catch throw of GDB error"}
+      -re "result = .*$gdb_prompt $"  {fail "catch throw of GDB error"}
+      -re "$gdb_prompt $"	      {fail "catch throw of GDB error"}
+  }
+}
+
+proc test_value_boolean {} {
+  # First, define a useful function to test booleans.
+  gdb_py_test_multiple "define function to test booleans" \
+    "python" "" \
+    "def test_bool (val):" "" \
+    "  if val:" "" \
+    "    print 'yay'" "" \
+    "  else:" "" \
+    "    print 'nay'" "" \
+    "end" ""
+
+  gdb_test "py test_bool (gdb.Value (True))" "yay" "check evaluation of true boolean value in expression"
+
+  gdb_test "py test_bool (gdb.Value (False))" "nay" "check evaluation of false boolean value in expression"
+
+  gdb_test "py test_bool (gdb.Value (5))" "yay" "check evaluation of true integer value in expression"
+
+  gdb_test "py test_bool (gdb.Value (0))" "nay" "check evaluation of false integer value in expression"
+
+  gdb_test "py test_bool (gdb.Value (5.2))" "yay" "check evaluation of true integer value in expression"
+
+  gdb_test "py test_bool (gdb.Value (0.0))" "nay" "check evaluation of false integer value in expression"
+}
+
+proc test_value_compare {} {
+  gdb_test "py print gdb.Value (1) < gdb.Value (1)" "False" "less than, equal"
+  gdb_test "py print gdb.Value (1) < gdb.Value (2)" "True" "less than, less"
+  gdb_test "py print gdb.Value (2) < gdb.Value (1)" "False" "less than, greater"
+  gdb_test "py print gdb.Value (2) < None" "False" "less than, None"
+
+  gdb_test "py print gdb.Value (1) <= gdb.Value (1)" "True" "less or equal, equal"
+  gdb_test "py print gdb.Value (1) <= gdb.Value (2)" "True" "less or equal, less"
+  gdb_test "py print gdb.Value (2) <= gdb.Value (1)" "False" "less or equal, greater"
+  gdb_test "py print gdb.Value (2) <= None" "False" "less or equal, None"
+
+  gdb_test "py print gdb.Value (1) == gdb.Value (1)" "True" "equality of gdb.Values"
+  gdb_test "py print gdb.Value (1) == gdb.Value (2)" "False" "inequality of gdb.Values"
+  gdb_test "py print gdb.Value (1) == 1.0" "True" "equality of gdb.Value with Python value"
+  gdb_test "py print gdb.Value (1) == 2" "False" "inequality of gdb.Value with Python value"
+  gdb_test "py print gdb.Value (1) == None" "False" "inequality of gdb.Value with None"
+
+  gdb_test "py print gdb.Value (1) != gdb.Value (1)" "False" "inequality, false"
+  gdb_test "py print gdb.Value (1) != gdb.Value (2)" "True" "inequality, true"
+  gdb_test "py print gdb.Value (1) != None" "True" "inequality, None"
+
+  gdb_test "py print gdb.Value (1) > gdb.Value (1)" "False" "greater than, equal"
+  gdb_test "py print gdb.Value (1) > gdb.Value (2)" "False" "greater than, less"
+  gdb_test "py print gdb.Value (2) > gdb.Value (1)" "True" "greater than, greater"
+  gdb_test "py print gdb.Value (2) > None" "True" "greater than, None"
+
+  gdb_test "py print gdb.Value (1) >= gdb.Value (1)" "True" "greater or equal, equal"
+  gdb_test "py print gdb.Value (1) >= gdb.Value (2)" "False" "greater or equal, less"
+  gdb_test "py print gdb.Value (2) >= gdb.Value (1)" "True" "greater or equal, greater"
+  gdb_test "py print gdb.Value (2) >= None" "True" "greater or equal, None"
+}
+
+proc test_value_in_inferior {} {
+  global gdb_prompt
+  global testfile
+
+  gdb_breakpoint [gdb_get_line_number "break to inspect struct and union"]
+  gdb_start_cmd
+
+  # Avoid race condition where a continue command in gdb_continue_to_breakpoint
+  # is issued too early.
+  gdb_test "" "$gdb_prompt"
+
+  gdb_continue_to_breakpoint "break to inspect struct and union"
+
+  # Just get inferior variable s in the value history, available to python.
+  gdb_test "print s" " = {a = 3, b = 5}" ""
+
+  gdb_py_test_silent_cmd "python s = gdb.get_value_from_history (0)" "get value from history" 1
+
+  gdb_test "python print 'result = ' + str(s\['a'\])" " = 3" "access element inside struct using 8-bit string name"
+  gdb_test "python print 'result = ' + str(s\[u'a'\])" " = 3" "access element inside struct using unicode name"
+
+  # Test dereferencing the argv pointer
+
+  # Just get inferior variable argv the value history, available to python.
+  gdb_test "print argv" " = \\(char \\*\\*\\) 0x.*" ""
+
+  gdb_py_test_silent_cmd "python argv = gdb.get_value_from_history (0)" "" 0
+  gdb_py_test_silent_cmd "python arg0 = argv.dereference ()" "dereference value" 1
+
+  # Check that the dereferenced value is sane
+  gdb_test "python print arg0" "0x.*$testfile\"" "verify dereferenced value"
+}
+
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test_multiple "python print 'hello, world!'" "verify python support" {
+    -re "not supported.*$gdb_prompt $"	{
+      unsupported "python support is disabled"
+      return -1
+    }
+    -re "$gdb_prompt $"	{}
+}
+
+test_value_creation
+test_value_numeric_ops
+test_value_boolean
+test_value_compare
+test_value_in_inferior
diff --git a/gdb/value.c b/gdb/value.c
index f3f2c72..07285c9 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -37,6 +37,8 @@
 #include "dfp.h"
 #include "objfiles.h"
 
+#include "python/python.h"
+
 /* Prototypes for exported functions. */
 
 void _initialize_values (void);
@@ -130,8 +132,8 @@ struct value
 
   /* Values are stored in a chain, so that they can be deleted easily
      over calls to the inferior.  Values assigned to internal
-     variables or put into the value history are taken off this
-     list.  */
+     variables, put into the value history or exposed to Python are
+     taken off this list.  */
   struct value *next;
 
   /* Register number if the value is from a register.  */
@@ -257,6 +259,31 @@ allocate_repeat_value (struct type *type, int count)
 					    type, range_type));
 }
 
+/* Needed if another module needs to maintain its on list of values.  */
+void
+value_prepend_to_list (struct value **head, struct value *val)
+{
+  val->next = *head;
+  *head = val;
+}
+
+/* Needed if another module needs to maintain its on list of values.  */
+void
+value_remove_from_list (struct value **head, struct value *val)
+{
+  struct value *prev;
+
+  if (*head == val)
+    *head = (*head)->next;
+  else
+    for (prev = *head; prev->next; prev = prev->next)
+      if (prev->next == val)
+      {
+	prev->next = val->next;
+	break;
+      }
+}
+
 /* Accessor methods.  */
 
 struct value *
@@ -916,6 +943,7 @@ preserve_values (struct objfile *objfile)
   htab_t copied_types;
   struct value_history_chunk *cur;
   struct internalvar *var;
+  struct value *val;
   int i;
 
   /* Create the hash table.  We allocate on the objfile's obstack, since
@@ -930,6 +958,9 @@ preserve_values (struct objfile *objfile)
   for (var = internalvars; var; var = var->next)
     preserve_one_value (var->value, objfile, copied_types);
 
+  for (val = values_in_python; val; val = val->next)
+    preserve_one_value (val, objfile, copied_types);
+
   htab_delete (copied_types);
 }
 
diff --git a/gdb/value.h b/gdb/value.h
index deb2629..f53d333 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -40,9 +40,15 @@ struct language_defn;
 
 struct value;
 
+/* Needed if another module needs to maintain its own list of values.  */
+
+void value_prepend_to_list (struct value **head, struct value *val);
+void value_remove_from_list (struct value **head, struct value *val);
+
 /* Values are stored in a chain, so that they can be deleted easily
-   over calls to the inferior.  Values assigned to internal variables
-   or put into the value history are taken off this list.  */
+   over calls to the inferior.  Values assigned to internal variables,
+   put into the value history or exposed to Python are taken off this
+   list.  */
 
 struct value *value_next (struct value *);
 


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