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: [rfc] expose gdb values to python


Eli Zaretskii wrote:
>> +@node Values From Inferior
>> +@subsubsection Values From Inferior
> 
> Please add some @cindex entry/entries here, which would be useful for
> someone who will look for this stuff via the index.

Right. Added a couple.
 
>> +@value{GDBN} provides values it obtains from the inferior program in an
>> +object of type @code{gdb.Value}.  This object keeps track of information
>> +related to the value such as its type, the address where it is kept in
>> +the inferior, and so on.
> 
> My assumption in reviewing Python-related manual sections is that the
> reader will generally _not_ be a proficient Python programmer, but
> rather someone who programs in another language, like C++ or Ada, and
> whose use of Python in GDB is just so to get away with whatever
> scripting the reader needs to craft for her current needs.

Agreed. It's a useful assumption.
 
> With that in mind, I think we should have as much examples and
> specific concrete information in these sections as possible, to make
> it easier for the reader to understand how to use these features
> without too many detours into Python manuals.  Abstract information,
> such as references to Python types, will not alone reach that goal.

I mostly agree, but in some cases I believe examples are not necessary
because IMHO some basic programming skills can be assumed, and a Python
integer is the same as an integer in any other language (I believe you are
referencing to my Python integer example). Examples for such cases will
most likely be obvious code snippets.

In any case, I added an example for that. If you think it's helpful, it can
stay.

> For example, in the above paragraph, would it help to describe the
> specific elements and methods of `gdb.Value', or give a couple of
> examples of their use in real life?  You mention the type and address
> of the inferior's value, but are there other useful members that the
> reader would want to know about?  And even for these 2, what kind of
> data types are they?

The objective of that paragraph was not to describe features of gdb.Value
available for direct use, but rather to give to the user a rationale of the
existence of the gdb.Value object (as opposed to having GDB return native
Python values). There's not much to describe regarding specific elements
and methods of gdb.Value since it has no element, and just one method which
I explicitly list and describe.

>From your comment above, I see that my text was not clear so I tried to
rephrase it. What do you think of this version?

>> +The following method is provided:
>> +
>> +@defmethod Value dereference
>> +If the @code{gdb.Value} object is of a pointer type, you can dereference
>> +it using the @code{dereference} method.  This gives you a new
>> +@code{gdb.Value} object for the pointed-to contents.
>> +@end defmethod
> 
> Again, a practical example of using this would be good to have.

I didn't provide an example originally because I thought that it was clear
enough from the description what the method does and how to use it. I'm
providing an example in this version, even though I think it's kind of
redundant. If you think it helps, it can stay.

This patch also fixes the comments from Daniel. Unfortunately, I just found
out that it won't compile with current CVS since it uses some
builtin_type_* variables which don't exist anymore. :-(

I post it as it is to get the documentation part reviewed, and will work to
fix this problem...
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
2008-09-27  Thiago Jung Bauermann  <bauerman@br.ibm.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.

Index: gdb.git/gdb/Makefile.in
===================================================================
--- gdb.git.orig/gdb/Makefile.in	2008-09-27 21:26:26.000000000 -0300
+++ gdb.git/gdb/Makefile.in	2008-09-27 21:28:44.000000000 -0300
@@ -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-
 	$(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
Index: gdb.git/gdb/configure
===================================================================
--- gdb.git.orig/gdb/configure	2008-09-27 21:26:26.000000000 -0300
+++ gdb.git/gdb/configure	2008-09-27 21:26:28.000000000 -0300
@@ -11704,10 +11704,10 @@ rm -f conftest.err conftest.$ac_objext c
 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
 
 
Index: gdb.git/gdb/configure.ac
===================================================================
--- gdb.git.orig/gdb/configure.ac	2008-09-27 21:26:26.000000000 -0300
+++ gdb.git/gdb/configure.ac	2008-09-27 21:26:28.000000000 -0300
@@ -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)
 
Index: gdb.git/gdb/doc/gdb.texinfo
===================================================================
--- gdb.git.orig/gdb/doc/gdb.texinfo	2008-09-27 21:26:26.000000000 -0300
+++ gdb.git/gdb/doc/gdb.texinfo	2008-09-27 21:26:28.000000000 -0300
@@ -17674,6 +17674,7 @@ situation, a Python @code{KeyboardInterr
 @menu
 * Basic Python::                Basic Python Functions.
 * Exception Handling::
+* Values From Inferior::
 @end menu
 
 @node Basic Python
@@ -17752,6 +17753,61 @@ message as its value, and the Python cal
 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
+@cindex python, working with values from inferior in
+
+@cindex @code{gdb.Value}
+@value{GDBN} provides values it obtains from the inferior program in an
+object of type @code{gdb.Value}.  This object is used so that @value{GDBN}
+can keep track of information related to the value such as its type and
+location in the inferior, and also to enable @value{GDBN} to fetch its
+contents from the inferior only when necessary.
+
+You don't need to be aware of such ancillary information in order to use
+@code{gdb.Value} objects.  You can directly use them in places which make
+sense for the type of the value they contain.  For instance, you can use
+the value of an integer variable in the inferior as if it was a Python
+integer variable.  For example, if @code{some_val} is a @code{gdb.Value}
+instance holding an integer (or even a floating point value), the following
+usage is valid:
+
+@smallexample
+bar = some_val + 2
+@end smallexample
+
+@code{bar} will also be a @code{gdb.Value} object.
+
+If the @code{gdb.Value} object is of a structure type or an instance of a
+class, its elements and methods are provided using 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.
+
+The following method is provided:
+
+@defmethod Value dereference
+If the @code{gdb.Value} object is of a pointer type, you can dereference
+it using the @code{dereference} method.  This gives you a new
+@code{gdb.Value} object for the pointed-to contents.  For example, if
+@code{some_val} is a @code{gdb.Value} instance holding a pointer to an
+integer (in C, that would be @code{int *}), the statement
+
+@smallexample
+bar = some_val.dereference ()
+@end smallexample
+
+will make @code{bar} a @code{gdb.Value} object holding the integer pointed
+to by @code{some_val}. @code{bar}  will be of integer type (in C, that
+would be @code{int}).
+@end defmethod
+
 @node Interpreters
 @chapter Command Interpreters
 @cindex command interpreters
Index: gdb.git/gdb/python/python-internal.h
===================================================================
--- gdb.git.orig/gdb/python/python-internal.h	2008-09-27 21:26:26.000000000 -0300
+++ gdb.git/gdb/python/python-internal.h	2008-09-27 21:26:28.000000000 -0300
@@ -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);
 
Index: gdb.git/gdb/python/python-value.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb.git/gdb/python/python-value.c	2008-09-27 21:26:28.000000000 -0300
@@ -0,0 +1,665 @@
+/* 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"
+
+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
+};
+
+/* 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_int, l);
+    }
+  else if (PyFloat_Check (other))
+    {
+      d = PyFloat_AsDouble (other);
+      if (PyErr_Occurred ())
+	return Py_NotImplemented;
+
+      other_val = value_from_double (builtin_type_double, 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:
+	  res_val = value_add (self_value->value, other_val);
+	  break;
+	case VALPY_SUB:
+	  res_val = value_sub (self_value->value, other_val);
+	  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_int, 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_int, l);
+    }
+  else if (PyFloat_Check (other))
+    {
+      DOUBLEST d;
+
+      d = PyFloat_AsDouble (other);
+      if (PyErr_Occurred ())
+	return NULL;
+
+      value_other = value_from_double (builtin_type_double, 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_bool, obj == Py_True);
+  else if (PyInt_Check (obj))
+    value = value_from_longest (builtin_type_int, PyInt_AsLong (obj));
+  else if (PyLong_Check (obj))
+    {
+      LONGEST l = PyLong_AsLongLong (obj);
+      if (! PyErr_Occurred ())
+	value = value_from_longest (builtin_type_long, l);
+    }
+  else if (PyFloat_Check (obj))
+    {
+      double d = PyFloat_AsDouble (obj);
+      if (! PyErr_Occurred ())
+	value = value_from_double (builtin_type_double, 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 */
Index: gdb.git/gdb/python/python.c
===================================================================
--- gdb.git.orig/gdb/python/python.c	2008-09-27 21:26:26.000000000 -0300
+++ gdb.git/gdb/python/python.c	2008-09-27 21:26:28.000000000 -0300
@@ -52,6 +52,8 @@ static PyObject *gdbpy_flush (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 s
   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
Index: gdb.git/gdb/python/python.h
===================================================================
--- gdb.git.orig/gdb/python/python.h	2008-09-27 21:26:26.000000000 -0300
+++ gdb.git/gdb/python/python.h	2008-09-27 21:26:28.000000000 -0300
@@ -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 */
Index: gdb.git/gdb/testsuite/gdb.python/python-value.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb.git/gdb/testsuite/gdb.python/python-value.c	2008-09-27 21:26:28.000000000 -0300
@@ -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 */
+}
Index: gdb.git/gdb/testsuite/gdb.python/python-value.exp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb.git/gdb/testsuite/gdb.python/python-value.exp	2008-09-27 21:26:28.000000000 -0300
@@ -0,0 +1,236 @@
+# 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
+}
+
+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 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" "acess element inside struct using 8-bit string name"
+  gdb_test "python print 'result = ' + str(s\[u'a'\])" " = 3" "acess 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
Index: gdb.git/gdb/value.c
===================================================================
--- gdb.git.orig/gdb/value.c	2008-09-27 21:26:26.000000000 -0300
+++ gdb.git/gdb/value.c	2008-09-27 21:26:28.000000000 -0300
@@ -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
 					    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);
 }
 
Index: gdb.git/gdb/value.h
===================================================================
--- gdb.git.orig/gdb/value.h	2008-09-27 21:26:26.000000000 -0300
+++ gdb.git/gdb/value.h	2008-09-27 21:26:28.000000000 -0300
@@ -40,9 +40,15 @@ struct language_defn;
 
 struct value;
 
+/* Needed if another module needs to maintain its on 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]