/* Python interface to values.
- Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
This file is part of GDB.
#include "infcall.h"
#include "expression.h"
#include "cp-abi.h"
+#include "python.h"
#ifdef HAVE_PYTHON
Py_XDECREF (self->dynamic_type);
- self->ob_type->tp_free (self);
+ Py_TYPE (self)->tp_free (self);
}
/* Helper to push a Value object on the global list. */
}
value_obj->value = value;
- value_incref (value);
+ release_value_or_incref (value);
value_obj->address = NULL;
value_obj->type = NULL;
value_obj->dynamic_type = NULL;
static PyObject *
valpy_dereference (PyObject *self, PyObject *args)
{
- struct value *res_val = NULL; /* Initialize to appease gcc warning. */
volatile struct gdb_exception except;
+ PyObject *result = NULL;
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ struct value *res_val;
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+
res_val = value_ind (((value_object *) self)->value);
+ result = value_to_value_object (res_val);
+ do_cleanups (cleanup);
}
GDB_PY_HANDLE_EXCEPTION (except);
- return value_to_value_object (res_val);
+ return result;
+}
+
+/* Given a value of a pointer type or a reference type, return the value
+ referenced. The difference between this function and valpy_dereference is
+ that the latter applies * unary operator to a value, which need not always
+ result in the value referenced. For example, for a value which is a reference
+ to an 'int' pointer ('int *'), valpy_dereference will result in a value of
+ type 'int' while valpy_referenced_value will result in a value of type
+ 'int *'. */
+
+static PyObject *
+valpy_referenced_value (PyObject *self, PyObject *args)
+{
+ volatile struct gdb_exception except;
+ PyObject *result = NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ struct value *self_val, *res_val;
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+
+ self_val = ((value_object *) self)->value;
+ switch (TYPE_CODE (check_typedef (value_type (self_val))))
+ {
+ case TYPE_CODE_PTR:
+ res_val = value_ind (self_val);
+ break;
+ case TYPE_CODE_REF:
+ res_val = coerce_ref (self_val);
+ break;
+ default:
+ error(_("Trying to get the referenced value from a value which is "
+ "neither a pointer nor a reference."));
+ }
+
+ result = value_to_value_object (res_val);
+ do_cleanups (cleanup);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return result;
}
/* Return "&value". */
static PyObject *
valpy_get_address (PyObject *self, void *closure)
{
- struct value *res_val = NULL; /* Initialize to appease gcc warning. */
value_object *val_obj = (value_object *) self;
volatile struct gdb_exception except;
{
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ struct value *res_val;
+ struct cleanup *cleanup
+ = make_cleanup_value_free_to_mark (value_mark ());
+
res_val = value_addr (val_obj->value);
+ val_obj->address = value_to_value_object (res_val);
+ do_cleanups (cleanup);
}
if (except.reason < 0)
{
val_obj->address = Py_None;
Py_INCREF (Py_None);
}
- else
- val_obj->address = value_to_value_object (res_val);
}
Py_XINCREF (val_obj->address);
TRY_CATCH (except, RETURN_MASK_ALL)
{
struct value *val = obj->value;
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
type = value_type (val);
CHECK_TYPEDEF (type);
/* Re-use object's static type. */
type = NULL;
}
+
+ do_cleanups (cleanup);
}
GDB_PY_HANDLE_EXCEPTION (except);
struct value *value = ((value_object *) self)->value;
const char *user_encoding = NULL;
static char *keywords[] = { "encoding", "length", NULL };
- PyObject *str_obj;
+ PyObject *str_obj = NULL;
volatile struct gdb_exception except;
if (!PyArg_ParseTupleAndKeywords (args, kw, "|s" GDB_PY_LL_ARG, keywords,
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+
if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
value = value_ind (value);
+
+ str_obj = gdbpy_create_lazy_string_object (value_address (value), length,
+ user_encoding,
+ value_type (value));
+
+ do_cleanups (cleanup);
}
GDB_PY_HANDLE_EXCEPTION (except);
- str_obj = gdbpy_create_lazy_string_object (value_address (value), length,
- user_encoding,
- value_type (value));
-
- return (PyObject *) str_obj;
+ return str_obj;
}
/* Implementation of gdb.Value.string ([encoding] [, errors]
static PyObject *
valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op)
{
- PyObject *type_obj;
+ PyObject *type_obj, *result = NULL;
struct type *type;
- struct value *res_val = NULL; /* Initialize to appease gcc warning. */
volatile struct gdb_exception except;
if (! PyArg_ParseTuple (args, "O", &type_obj))
TRY_CATCH (except, RETURN_MASK_ALL)
{
struct value *val = ((value_object *) self)->value;
+ struct value *res_val;
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
if (op == UNOP_DYNAMIC_CAST)
res_val = value_dynamic_cast (type, val);
gdb_assert (op == UNOP_CAST);
res_val = value_cast (type, val);
}
+
+ result = value_to_value_object (res_val);
+ do_cleanups (cleanup);
}
GDB_PY_HANDLE_EXCEPTION (except);
- return value_to_value_object (res_val);
+ return result;
}
/* Implementation of the "cast" method. */
{
value_object *self_value = (value_object *) self;
char *field = NULL;
- struct value *res_val = NULL;
volatile struct gdb_exception except;
+ PyObject *result = NULL;
if (gdbpy_is_string (key))
{
TRY_CATCH (except, RETURN_MASK_ALL)
{
struct value *tmp = self_value->value;
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+ struct value *res_val = NULL;
if (field)
res_val = value_struct_elt (&tmp, NULL, field, 0, NULL);
res_val = value_subscript (tmp, value_as_long (idx));
}
}
+
+ if (res_val)
+ result = value_to_value_object (res_val);
+ do_cleanups (cleanup);
}
xfree (field);
GDB_PY_HANDLE_EXCEPTION (except);
- return res_val ? value_to_value_object (res_val) : NULL;
+ return result;
}
static int
static PyObject *
valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
{
- struct value *return_value = NULL;
Py_ssize_t args_count;
volatile struct gdb_exception except;
struct value *function = ((value_object *) self)->value;
struct value **vargs = NULL;
struct type *ftype = NULL;
+ struct value *mark = value_mark ();
+ PyObject *result = NULL;
TRY_CATCH (except, RETURN_MASK_ALL)
{
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (mark);
+ struct value *return_value;
+
return_value = call_function_by_hand (function, args_count, vargs);
+ result = value_to_value_object (return_value);
+ do_cleanups (cleanup);
}
GDB_PY_HANDLE_EXCEPTION (except);
- return value_to_value_object (return_value);
+ return result;
}
/* Called by the Python interpreter to obtain string representation
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
static PyObject *
valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
{
- struct value *res_val = NULL; /* Initialize to appease gcc warning. */
volatile struct gdb_exception except;
+ PyObject *result = NULL;
TRY_CATCH (except, RETURN_MASK_ALL)
{
struct value *arg1, *arg2;
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+ struct value *res_val = NULL;
/* 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
res_val = value_binop (arg1, arg2, BINOP_BITWISE_XOR);
break;
}
+
+ if (res_val)
+ result = value_to_value_object (res_val);
+
+ do_cleanups (cleanup);
}
GDB_PY_HANDLE_EXCEPTION (except);
- return res_val ? value_to_value_object (res_val) : NULL;
+ return result;
}
static PyObject *
static PyObject *
valpy_negative (PyObject *self)
{
- struct value *val = NULL;
volatile struct gdb_exception except;
+ PyObject *result = NULL;
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ /* Perhaps overkill, but consistency has some virtue. */
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+ struct value *val;
+
val = value_neg (((value_object *) self)->value);
+ result = value_to_value_object (val);
+ do_cleanups (cleanup);
}
GDB_PY_HANDLE_EXCEPTION (except);
- return value_to_value_object (val);
+ return result;
}
static PyObject *
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+
if (value_less (value, value_zero (value_type (value), not_lval)))
isabs = 0;
+
+ do_cleanups (cleanup);
}
GDB_PY_HANDLE_EXCEPTION (except);
struct type *type;
int nonzero = 0; /* Appease GCC warning. */
- type = check_typedef (value_type (self_value->value));
-
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ type = check_typedef (value_type (self_value->value));
+
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)
valpy_richcompare (PyObject *self, PyObject *other, int op)
{
int result = 0;
- struct value *value_other;
volatile struct gdb_exception except;
if (other == Py_None)
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ struct value *value_other, *mark = value_mark ();
+ struct cleanup *cleanup;
+
value_other = convert_value_from_python (other);
if (value_other == NULL)
{
break;
}
+ cleanup = make_cleanup_value_free_to_mark (mark);
+
switch (op) {
case Py_LT:
result = value_less (((value_object *) self)->value, value_other);
result = -1;
break;
}
+
+ do_cleanups (cleanup);
}
GDB_PY_HANDLE_EXCEPTION (except);
|| (ptr_ok && TYPE_CODE (type) == TYPE_CODE_PTR));
}
+#ifndef IS_PY3K
/* Implements conversion to int. */
static PyObject *
valpy_int (PyObject *self)
return gdb_py_object_from_longest (l);
}
+#endif
/* Implements conversion to long. */
static PyObject *
value_to_value_object (struct value *val)
{
value_object *val_obj;
- volatile struct gdb_exception except;
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- if (value_lazy (val))
- value_fetch_lazy (val);
- }
- GDB_PY_HANDLE_EXCEPTION (except);
-
val_obj = PyObject_New (value_object, &value_object_type);
if (val_obj != NULL)
{
val_obj->value = val;
- value_incref (val);
+ release_value_or_incref (val);
val_obj->address = NULL;
val_obj->type = NULL;
val_obj->dynamic_type = NULL;
convert_value_from_python (PyObject *obj)
{
struct value *value = NULL; /* -Wall */
- struct cleanup *old;
volatile struct gdb_exception except;
int cmp;
s = python_string_to_target_string (obj);
if (s != NULL)
{
+ struct cleanup *old;
+
old = make_cleanup (xfree, s);
value = value_cstring (s, strlen (s), builtin_type_pychar);
do_cleanups (old);
value = value_copy (((value_object *) result)->value);
}
else
+#ifdef IS_PY3K
+ PyErr_Format (PyExc_TypeError,
+ _("Could not convert Python object: %S."), obj);
+#else
PyErr_Format (PyExc_TypeError,
_("Could not convert Python object: %s."),
PyString_AsString (PyObject_Str (obj)));
+#endif
}
if (except.reason < 0)
{
{ "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 */
};
reinterpret_cast operator."
},
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
+ { "referenced_value", valpy_referenced_value, METH_NOARGS,
+ "Return the value referenced by a TYPE_CODE_REF or TYPE_CODE_PTR value." },
{ "lazy_string", (PyCFunction) valpy_lazy_string,
METH_VARARGS | METH_KEYWORDS,
"lazy_string ([encoding] [, length]) -> lazy_string\n\
{ "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 */
};
valpy_add,
valpy_subtract,
valpy_multiply,
+#ifndef IS_PY3K
valpy_divide,
+#endif
valpy_remainder,
NULL, /* nb_divmod */
valpy_power, /* nb_power */
valpy_and, /* nb_and */
valpy_xor, /* nb_xor */
valpy_or, /* nb_or */
+#ifdef IS_PY3K
+ valpy_long, /* nb_int */
+ NULL, /* reserved */
+#else
NULL, /* nb_coerce */
valpy_int, /* nb_int */
valpy_long, /* nb_long */
+#endif
valpy_float, /* nb_float */
+#ifndef IS_PY3K
NULL, /* nb_oct */
- NULL /* nb_hex */
+ NULL, /* nb_hex */
+#endif
+ NULL, /* nb_inplace_add */
+ NULL, /* nb_inplace_subtract */
+ NULL, /* nb_inplace_multiply */
+ NULL, /* nb_inplace_remainder */
+ NULL, /* nb_inplace_power */
+ NULL, /* nb_inplace_lshift */
+ NULL, /* nb_inplace_rshift */
+ NULL, /* nb_inplace_and */
+ NULL, /* nb_inplace_xor */
+ NULL, /* nb_inplace_or */
+ NULL, /* nb_floor_divide */
+ valpy_divide /* nb_true_divide */
};
static PyMappingMethods value_object_as_mapping = {
};
PyTypeObject value_object_type = {
- PyObject_HEAD_INIT (NULL)
- 0, /*ob_size*/
+ PyVarObject_HEAD_INIT (NULL, 0)
"gdb.Value", /*tp_name*/
sizeof (value_object), /*tp_basicsize*/
0, /*tp_itemsize*/