]> Git Repo - binutils.git/blobdiff - gdb/python/py-value.c
2011-10-27 Phil Muldoon <[email protected]>
[binutils.git] / gdb / python / py-value.c
index aa180428574a3ae7d4412255442581cea7ef0d03..15c183a3017fba80df276a4c09cad26fa4bc9438 100644 (file)
@@ -1,6 +1,6 @@
 /* Python interface to values.
 
-   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "valprint.h"
 #include "infcall.h"
 #include "expression.h"
+#include "cp-abi.h"
 
 #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
+   target types here to remain consistent with the values system in
    GDB (which uses target arithmetic).  */
 
 /* Python's integer type corresponds to C's long type.  */
@@ -62,6 +63,7 @@ typedef struct value_object {
   struct value *value;
   PyObject *address;
   PyObject *type;
+  PyObject *dynamic_type;
 } value_object;
 
 /* List of all values which are currently exposed to Python. It is
@@ -101,6 +103,8 @@ valpy_dealloc (PyObject *obj)
       Py_DECREF (self->type);
     }
 
+  Py_XDECREF (self->dynamic_type);
+
   self->ob_type->tp_free (self);
 }
 
@@ -115,7 +119,8 @@ note_value (value_object *value_obj)
   values_in_python = value_obj;
 }
 
-/* Called when a new gdb.Value object needs to be allocated.  */
+/* Called when a new gdb.Value object needs to be allocated.  Returns NULL on
+   error, with a python exception set.  */
 static PyObject *
 valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
 {
@@ -148,6 +153,7 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
   value_incref (value);
   value_obj->address = NULL;
   value_obj->type = NULL;
+  value_obj->dynamic_type = NULL;
   note_value (value_obj);
 
   return (PyObject *) value_obj;
@@ -203,7 +209,7 @@ valpy_get_address (PyObject *self, void *closure)
        val_obj->address = value_to_value_object (res_val);
     }
 
-  Py_INCREF (val_obj->address);
+  Py_XINCREF (val_obj->address);
 
   return val_obj->address;
 }
@@ -218,15 +224,78 @@ valpy_get_type (PyObject *self, void *closure)
     {
       obj->type = type_to_type_object (value_type (obj->value));
       if (!obj->type)
-       {
-         obj->type = Py_None;
-         Py_INCREF (obj->type);
-       }
+       return NULL;
     }
   Py_INCREF (obj->type);
   return obj->type;
 }
 
+/* Return dynamic type of the value.  */
+
+static PyObject *
+valpy_get_dynamic_type (PyObject *self, void *closure)
+{
+  value_object *obj = (value_object *) self;
+  volatile struct gdb_exception except;
+  struct type *type = NULL;
+
+  if (obj->dynamic_type != NULL)
+    {
+      Py_INCREF (obj->dynamic_type);
+      return obj->dynamic_type;
+    }
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      struct value *val = obj->value;
+
+      type = value_type (val);
+      CHECK_TYPEDEF (type);
+
+      if (((TYPE_CODE (type) == TYPE_CODE_PTR)
+          || (TYPE_CODE (type) == TYPE_CODE_REF))
+         && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
+       {
+         struct value *target;
+         int was_pointer = TYPE_CODE (type) == TYPE_CODE_PTR;
+
+         target = value_ind (val);
+         type = value_rtti_type (target, NULL, NULL, NULL);
+
+         if (type)
+           {
+             if (was_pointer)
+               type = lookup_pointer_type (type);
+             else
+               type = lookup_reference_type (type);
+           }
+       }
+      else if (TYPE_CODE (type) == TYPE_CODE_CLASS)
+       type = value_rtti_type (val, NULL, NULL, NULL);
+      else
+       {
+         /* Re-use object's static type.  */
+         type = NULL;
+       }
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (type == NULL)
+    {
+      /* Ensure that the TYPE field is ready.  */
+      if (!valpy_get_type (self, NULL))
+       return NULL;
+      /* We don't need to incref here, because valpy_get_type already
+        did it for us.  */
+      obj->dynamic_type = obj->type;
+    }
+  else
+    obj->dynamic_type = type_to_type_object (type);
+
+  Py_INCREF (obj->dynamic_type);
+  return obj->dynamic_type;
+}
+
 /* Implementation of gdb.Value.lazy_string ([encoding] [, length]) ->
    string.  Return a PyObject representing a lazy_string_object type.
    A lazy string is a pointer to a string with an optional encoding and
@@ -238,21 +307,27 @@ valpy_get_type (PyObject *self, void *closure)
 static PyObject *
 valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
 {
-  int length = -1;
+  gdb_py_longest length = -1;
   struct value *value = ((value_object *) self)->value;
   const char *user_encoding = NULL;
   static char *keywords[] = { "encoding", "length", NULL };
   PyObject *str_obj;
+  volatile struct gdb_exception except;
 
-  if (!PyArg_ParseTupleAndKeywords (args, kw, "|si", keywords,
+  if (!PyArg_ParseTupleAndKeywords (args, kw, "|s" GDB_PY_LL_ARG, keywords,
                                    &user_encoding, &length))
     return NULL;
 
-  if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
-    value = value_ind (value);
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
+       value = value_ind (value);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
 
   str_obj = gdbpy_create_lazy_string_object (value_address (value), length,
-                                            user_encoding, value_type (value));
+                                            user_encoding,
+                                            value_type (value));
 
   return (PyObject *) str_obj;
 }
@@ -370,7 +445,7 @@ valpy_length (PyObject *self)
 }
 
 /* Given string name of an element inside structure, return its value
-   object.  */
+   object.  Returns NULL on error, with a python exception set.  */
 static PyObject *
 valpy_getitem (PyObject *self, PyObject *key)
 {
@@ -409,7 +484,7 @@ valpy_getitem (PyObject *self, PyObject *key)
              type = check_typedef (value_type (tmp));
              if (TYPE_CODE (type) != TYPE_CODE_ARRAY
                  && TYPE_CODE (type) != TYPE_CODE_PTR)
-                 error_("Cannot subscript requested type."));
+                 error (_("Cannot subscript requested type."));
              else
                res_val = value_subscript (tmp, value_as_long (idx));
            }
@@ -431,7 +506,7 @@ valpy_setitem (PyObject *self, PyObject *key, PyObject *value)
 }
 
 /* Called by the Python interpreter to perform an inferior function
-   call on the value.  */
+   call on the value.  Returns NULL on error, with a python exception set.  */
 static PyObject *
 valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
 {
@@ -440,7 +515,13 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
   volatile struct gdb_exception except;
   struct value *function = ((value_object *) self)->value;
   struct value **vargs = NULL;
-  struct type *ftype = check_typedef (value_type (function));
+  struct type *ftype = NULL;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      ftype = check_typedef (value_type (function));
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
 
   if (TYPE_CODE (ftype) != TYPE_CODE_FUNC)
     {
@@ -449,6 +530,13 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
       return NULL;
     }
 
+  if (! PyTuple_Check (args))
+    {
+      PyErr_SetString (PyExc_TypeError,
+                      _("Inferior arguments must be provided in a tuple."));
+      return NULL;
+    }
+
   args_count = PyTuple_Size (args);
   if (args_count > 0)
     {
@@ -483,8 +571,6 @@ static PyObject *
 valpy_str (PyObject *self)
 {
   char *s = NULL;
-  struct ui_file *stb;
-  struct cleanup *old_chain;
   PyObject *result;
   struct value_print_options opts;
   volatile struct gdb_exception except;
@@ -492,19 +578,19 @@ valpy_str (PyObject *self)
   get_user_print_options (&opts);
   opts.deref_ref = 0;
 
-  stb = mem_fileopen ();
-  old_chain = make_cleanup_ui_file_delete (stb);
-
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
+      struct ui_file *stb = mem_fileopen ();
+      struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
+
       common_val_print (((value_object *) self)->value, stb, 0,
                        &opts, python_language);
       s = ui_file_xstrdup (stb, NULL);
+
+      do_cleanups (old_chain);
     }
   GDB_PY_HANDLE_EXCEPTION (except);
 
-  do_cleanups (old_chain);
-
   result = PyUnicode_Decode (s, strlen (s), host_charset (), NULL);
   xfree (s);
 
@@ -516,13 +602,58 @@ static PyObject *
 valpy_get_is_optimized_out (PyObject *self, void *closure)
 {
   struct value *value = ((value_object *) self)->value;
+  int opt = 0;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      opt = value_optimized_out (value);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
 
-  if (value_optimized_out (value))
+  if (opt)
     Py_RETURN_TRUE;
 
   Py_RETURN_FALSE;
 }
 
+/* Implements gdb.Value.is_lazy.  */
+static PyObject *
+valpy_get_is_lazy (PyObject *self, void *closure)
+{
+  struct value *value = ((value_object *) self)->value;
+  int opt = 0;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      opt = value_lazy (value);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (opt)
+    Py_RETURN_TRUE;
+
+  Py_RETURN_FALSE;
+}
+
+/* Implements gdb.Value.fetch_lazy ().  */
+static PyObject *
+valpy_fetch_lazy (PyObject *self, PyObject *args)
+{
+  struct value *value = ((value_object *) self)->value;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (value_lazy (value))
+       value_fetch_lazy (value);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  Py_RETURN_NONE;
+}
+
 /* Calculate and return the address of the PyObject as the value of
    the builtin __hash__ call.  */
 static long 
@@ -551,7 +682,8 @@ enum valpy_opcode
   ((TYPE_CODE (TYPE) == TYPE_CODE_REF) ? (TYPE_TARGET_TYPE (TYPE)) : (TYPE))
 
 /* Returns a value object which is the result of applying the operation
-   specified by OPCODE to the given arguments.  */
+   specified by OPCODE to the given arguments.  Returns NULL on error, with
+   a python exception set.  */
 static PyObject *
 valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
 {
@@ -723,33 +855,53 @@ static PyObject *
 valpy_absolute (PyObject *self)
 {
   struct value *value = ((value_object *) self)->value;
+  volatile struct gdb_exception except;
+  int isabs = 1;
 
-  if (value_less (value, value_zero (value_type (value), not_lval)))
-    return valpy_negative (self);
-  else
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (value_less (value, value_zero (value_type (value), not_lval)))
+       isabs = 0;
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (isabs)
     return valpy_positive (self);
+  else
+    return valpy_negative (self);
 }
 
 /* Implements boolean evaluation of gdb.Value.  */
 static int
 valpy_nonzero (PyObject *self)
 {
+  volatile struct gdb_exception except;
   value_object *self_value = (value_object *) self;
   struct type *type;
+  int nonzero = 0; /* Appease GCC warning.  */
 
   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),
-                            gdbarch_byte_order (get_type_arch (type)));
-  else
-    /* All other values are True.  */
-    return 1;
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (is_integral_type (type) || TYPE_CODE (type) == TYPE_CODE_PTR)
+       nonzero = !!value_as_long (self_value->value);
+      else if (TYPE_CODE (type) == TYPE_CODE_FLT)
+       nonzero = value_as_double (self_value->value) != 0;
+      else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+       nonzero = !decimal_is_zero (value_contents (self_value->value),
+                                TYPE_LENGTH (type),
+                                gdbarch_byte_order (get_type_arch (type)));
+      else
+       /* All other values are True.  */
+       nonzero = 1;
+    }
+  /* This is not documented in the Python documentation, but if this
+     function fails, return -1 as slot_nb_nonzero does (the default
+     Python nonzero function).  */
+  GDB_PY_SET_HANDLE_EXCEPTION (except);
+
+  return nonzero;
 }
 
 /* Implements ~ for value objects.  */
@@ -803,7 +955,8 @@ valpy_xor (PyObject *self, PyObject *other)
   return valpy_binop (VALPY_BITXOR, self, other);
 }
 
-/* Implements comparison operations for value objects.  */
+/* Implements comparison operations for value objects.  Returns NULL on error,
+   with a python exception set.  */
 static PyObject *
 valpy_richcompare (PyObject *self, PyObject *other, int op)
 {
@@ -884,7 +1037,6 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
 static int
 is_intlike (struct type *type, int ptr_ok)
 {
-  CHECK_TYPEDEF (type);
   return (TYPE_CODE (type) == TYPE_CODE_INT
          || TYPE_CODE (type) == TYPE_CODE_ENUM
          || TYPE_CODE (type) == TYPE_CODE_BOOL
@@ -901,28 +1053,17 @@ valpy_int (PyObject *self)
   LONGEST l = 0;
   volatile struct gdb_exception except;
 
-  CHECK_TYPEDEF (type);
-  if (!is_intlike (type, 0))
-    {
-      PyErr_SetString (PyExc_RuntimeError, 
-                      _("Cannot convert value to int."));
-      return NULL;
-    }
-
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
+      CHECK_TYPEDEF (type);
+      if (!is_intlike (type, 0))
+       error (_("Cannot convert value to int."));
+
       l = value_as_long (value);
     }
   GDB_PY_HANDLE_EXCEPTION (except);
 
-#ifdef HAVE_LONG_LONG          /* Defined by Python.  */
-  /* If we have 'long long', and the value overflows a 'long', use a
-     Python Long; otherwise use a Python Int.  */
-  if (sizeof (l) > sizeof (long) && (l > PyInt_GetMax ()
-                                    || l < (- (LONGEST) PyInt_GetMax ()) - 1))
-    return PyLong_FromLongLong (l);
-#endif
-  return PyInt_FromLong (l);
+  return gdb_py_object_from_longest (l);
 }
 
 /* Implements conversion to long.  */
@@ -934,24 +1075,18 @@ valpy_long (PyObject *self)
   LONGEST l = 0;
   volatile struct gdb_exception except;
 
-  if (!is_intlike (type, 1))
-    {
-      PyErr_SetString (PyExc_RuntimeError, 
-                      _("Cannot convert value to long."));
-      return NULL;
-    }
-
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
+      CHECK_TYPEDEF (type);
+
+      if (!is_intlike (type, 1))
+       error (_("Cannot convert value to long."));
+
       l = value_as_long (value);
     }
   GDB_PY_HANDLE_EXCEPTION (except);
 
-#ifdef HAVE_LONG_LONG          /* Defined by Python.  */
-  return PyLong_FromLongLong (l);
-#else
-  return PyLong_FromLong (l);
-#endif
+  return gdb_py_long_from_longest (l);
 }
 
 /* Implements conversion to float.  */
@@ -963,16 +1098,13 @@ valpy_float (PyObject *self)
   double d = 0;
   volatile struct gdb_exception except;
 
-  CHECK_TYPEDEF (type);
-  if (TYPE_CODE (type) != TYPE_CODE_FLT)
-    {
-      PyErr_SetString (PyExc_RuntimeError, 
-                      _("Cannot convert value to float."));
-      return NULL;
-    }
-
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
+      CHECK_TYPEDEF (type);
+
+      if (TYPE_CODE (type) != TYPE_CODE_FLT)
+       error (_("Cannot convert value to float."));
+
       d = value_as_double (value);
     }
   GDB_PY_HANDLE_EXCEPTION (except);
@@ -994,6 +1126,7 @@ value_to_value_object (struct value *val)
       value_incref (val);
       val_obj->address = NULL;
       val_obj->type = NULL;
+      val_obj->dynamic_type = NULL;
       note_value (val_obj);
     }
 
@@ -1100,13 +1233,13 @@ convert_value_from_python (PyObject *obj)
       else if (gdbpy_is_lazy_string (obj))
        {
          PyObject *result;
-         PyObject *function = PyString_FromString ("value");
 
-         result = PyObject_CallMethodObjArgs (obj, function,  NULL);
+         result = PyObject_CallMethodObjArgs (obj, gdbpy_value_cst,  NULL);
          value = value_copy (((value_object *) result)->value);
        }
       else
-       PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s."),
+       PyErr_Format (PyExc_TypeError,
+                     _("Could not convert Python object: %s."),
                      PyString_AsString (PyObject_Str (obj)));
     }
   if (except.reason < 0)
@@ -1166,9 +1299,16 @@ static PyGetSetDef value_object_getset[] = {
   { "address", valpy_get_address, NULL, "The address of the value.",
     NULL },
   { "is_optimized_out", valpy_get_is_optimized_out, NULL,
-    "Boolean telling whether the value is optimized out (i.e., not available).",
+    "Boolean telling whether the value is optimized "
+    "out (i.e., not available).",
     NULL },
   { "type", valpy_get_type, NULL, "Type of the value.", NULL },
+  { "dynamic_type", valpy_get_dynamic_type, NULL,
+    "Dynamic type of the value.", NULL },
+  { "is_lazy", valpy_get_is_lazy, NULL,
+    "Boolean telling whether the value is lazy (not fetched yet\n\
+from the inferior).  A lazy value is fetched when needed, or when\n\
+the \"fetch_lazy()\" method is called.", NULL },
   {NULL}  /* Sentinel */
 };
 
@@ -1184,12 +1324,15 @@ Cast the value to the supplied type, as if by the C++\n\
 reinterpret_cast operator."
   },
   { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
-  { "lazy_string", (PyCFunction) valpy_lazy_string, METH_VARARGS | METH_KEYWORDS,
+  { "lazy_string", (PyCFunction) valpy_lazy_string,
+    METH_VARARGS | METH_KEYWORDS,
     "lazy_string ([encoding]  [, length]) -> lazy_string\n\
 Return a lazy string representation of the value." },
   { "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
     "string ([encoding] [, errors] [, length]) -> string\n\
 Return Unicode string representation of the value." },
+  { "fetch_lazy", valpy_fetch_lazy, METH_NOARGS, 
+    "Fetches the value from the inferior, if it was lazy." },
   {NULL}  /* Sentinel */
 };
 
@@ -1246,7 +1389,8 @@ PyTypeObject value_object_type = {
   0,                             /*tp_getattro*/
   0,                             /*tp_setattro*/
   0,                             /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,  /*tp_flags*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES
+  | Py_TPFLAGS_BASETYPE,         /*tp_flags*/
   "GDB value object",            /* tp_doc */
   0,                             /* tp_traverse */
   0,                             /* tp_clear */
This page took 0.042826 seconds and 4 git commands to generate.