diff options
author | Thiago Jung Bauermann <bauerman@br.ibm.com> | 2009-02-04 21:55:40 +0000 |
---|---|---|
committer | Thiago Jung Bauermann <bauerman@br.ibm.com> | 2009-02-04 21:55:40 +0000 |
commit | 08c637dee28a25da97418745fbebb26b2fba8eef (patch) | |
tree | 7d7d670deff8204aa4f5deb9152b739b91e0ef53 /gdb/python | |
parent | 20261af84c27478a2333f573702ba2b6e4a8b038 (diff) | |
download | gdb-08c637dee28a25da97418745fbebb26b2fba8eef.zip gdb-08c637dee28a25da97418745fbebb26b2fba8eef.tar.gz gdb-08c637dee28a25da97418745fbebb26b2fba8eef.tar.bz2 |
gdb/
2009-02-04 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Phil Muldoon <pmuldoon@redhat.com>
* python/python-internal.h (gdbpy_get_value_from_history): Rename
prototype to gdbpy_history.
(gdbpy_is_string): Declare.
(python_string_to_host_string): Declare.
* python/python-utils.c (gdbpy_is_string): New function.
(unicode_to_encoded_string): New function.
(unicode_to_target_string): Use it.
(python_string_to_host_string): New function.
* python/python-value.c (valpy_address): New function.
(convert_value_from_python): Use gdbpy_is_string. Change to throw
Python exception instead of a GDB exception on error. Properly check
Python booleans.
(valpy_getitem): Convert field name to host string. Handle array
accesses. Adapt to new behaviour of convert_value_from_python.
(valpy_new): Adapt to new behaviour of convert_value_from_python.
(enum valpy_opcode) <VALPY_LSH, VALPY_RSH, VALPY_BITAND,
VALPY_BITXOR, VALPY_BITOR>: New constants.
(valpy_binop): Update. Adapt to new behaviour of
convert_value_from_python.
(valpy_invert): New function.
(valpy_lsh): Likewise.
(valpy_rsh): Likewise.
(valpy_and): Likewise.
(valpy_or): Likewise.
(valpy_xor): Likewise.
(valpy_richcompare): Call convert_value_from_python instead of doing
conversions itself.
(is_intlike, valpy_int, valpy_long, valpy_float): New functions.
(gdbpy_get_value_from_history): Rename
function to gdbpy_history.
(gdbpy_initialize_values): Don't set tp_new.
(value_object_type): Add valpy_new.
(value_object_methods): Add `address' entry.
(value_object_as_number): Update for new methods.
* python/python.c (GdbMethods): Rename entry from
`get_value_from_history' to `history'.
gdb/doc/
2009-02-04 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Basic Python): Document gdb.history.
gdb/testsuite/
2009-02-04 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* gdb.python/python-value.exp: Use `gdb.history' instead of
`gdb.value_from_history'.
(test_value_numeric_ops): Add test for conversion of enum constant.
* gdb.python/python-value.c (enum e): New type.
(evalue): New global.
(main): Use argv.
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/python-internal.h | 4 | ||||
-rw-r--r-- | gdb/python/python-utils.c | 54 | ||||
-rw-r--r-- | gdb/python/python-value.c | 384 | ||||
-rw-r--r-- | gdb/python/python.c | 2 |
4 files changed, 339 insertions, 105 deletions
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 4e9da33..672d8a4 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -63,7 +63,7 @@ struct value; extern PyObject *gdb_module; extern PyTypeObject value_object_type; -PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args); +PyObject *gdbpy_history (PyObject *self, PyObject *args); PyObject *value_to_value_object (struct value *v); @@ -90,5 +90,7 @@ void gdbpy_print_stack (void); PyObject *python_string_to_unicode (PyObject *obj); char *unicode_to_target_string (PyObject *unicode_str); char *python_string_to_target_string (PyObject *obj); +char *python_string_to_host_string (PyObject *obj); +int gdbpy_is_string (PyObject *obj); #endif /* GDB_PYTHON_INTERNAL_H */ diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c index 9aae43f..6a95939 100644 --- a/gdb/python/python-utils.c +++ b/gdb/python/python-utils.c @@ -95,26 +95,37 @@ python_string_to_unicode (PyObject *obj) } /* Returns a newly allocated string with the contents of the given unicode - string object converted to the target's charset. If an error occurs during - the conversion, NULL will be returned and a python exception will be set. + string object converted to CHARSET. If an error occurs during the + conversion, NULL will be returned and a python exception will be set. The caller is responsible for xfree'ing the string. */ -char * -unicode_to_target_string (PyObject *unicode_str) +static char * +unicode_to_encoded_string (PyObject *unicode_str, const char *charset) { - char *target_string; + char *result; PyObject *string; - /* Translate string to target's charset. */ - string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL); + /* Translate string to named charset. */ + string = PyUnicode_AsEncodedString (unicode_str, charset, NULL); if (string == NULL) return NULL; - target_string = xstrdup (PyString_AsString (string)); + result = xstrdup (PyString_AsString (string)); Py_DECREF (string); - return target_string; + return result; +} + +/* Returns a newly allocated string with the contents of the given unicode + string object converted to the target's charset. If an error occurs during + the conversion, NULL will be returned and a python exception will be set. + + The caller is responsible for xfree'ing the string. */ +char * +unicode_to_target_string (PyObject *unicode_str) +{ + return unicode_to_encoded_string (unicode_str, target_charset ()); } /* Converts a python string (8-bit or unicode) to a target string in @@ -132,3 +143,28 @@ python_string_to_target_string (PyObject *obj) return unicode_to_target_string (str); } + +/* Converts a python string (8-bit or unicode) to a target string in + the host's charset. Returns NULL on error, with a python exception set. + + The caller is responsible for xfree'ing the string. */ +char * +python_string_to_host_string (PyObject *obj) +{ + PyObject *str; + + str = python_string_to_unicode (obj); + if (str == NULL) + return NULL; + + return unicode_to_encoded_string (str, host_charset ()); +} + +/* Return true if OBJ is a Python string or unicode object, false + otherwise. */ + +int +gdbpy_is_string (PyObject *obj) +{ + return PyString_Check (obj) || PyUnicode_Check (obj); +} diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c index 92e0431..420d26f 100644 --- a/gdb/python/python-value.c +++ b/gdb/python/python-value.c @@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "defs.h" +#include "gdb_assert.h" #include "charset.h" #include "value.h" #include "exceptions.h" @@ -79,7 +80,6 @@ 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) { @@ -96,16 +96,11 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords) return NULL; } - TRY_CATCH (except, RETURN_MASK_ALL) - { - value = convert_value_from_python (PyTuple_GetItem (args, 0)); - } - if (except.reason < 0) + value = convert_value_from_python (PyTuple_GetItem (args, 0)); + if (value == NULL) { subtype->tp_free (value_obj); - return PyErr_Format (except.reason == RETURN_QUIT - ? PyExc_KeyboardInterrupt : PyExc_TypeError, - "%s", except.message); + return NULL; } value_obj->value = value; @@ -132,6 +127,22 @@ valpy_dereference (PyObject *self, PyObject *args) return value_to_value_object (res_val); } +/* Return "&value". */ +static PyObject * +valpy_address (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_addr (((value_object *) self)->value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (res_val); +} + static Py_ssize_t valpy_length (PyObject *self) { @@ -147,26 +158,40 @@ static PyObject * valpy_getitem (PyObject *self, PyObject *key) { value_object *self_value = (value_object *) self; - char *field; + char *field = NULL; + struct value *idx = NULL; 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); + if (gdbpy_is_string (key)) + { + field = python_string_to_host_string (key); + if (field == NULL) + return NULL; + } TRY_CATCH (except, RETURN_MASK_ALL) { struct value *tmp = self_value->value; - res_val = value_struct_elt (&tmp, NULL, field, 0, NULL); + + if (field) + res_val = value_struct_elt (&tmp, NULL, field, 0, NULL); + else + { + /* Assume we are attempting an array access, and let the + value code throw an exception if the index has an invalid + type. */ + struct value *idx = convert_value_from_python (key); + if (idx == NULL) + return NULL; + + res_val = value_subscript (tmp, idx); + } } + if (field) + xfree (field); GDB_PY_HANDLE_EXCEPTION (except); - do_cleanups (old); - return value_to_value_object (res_val); } @@ -220,7 +245,12 @@ enum valpy_opcode VALPY_MUL, VALPY_DIV, VALPY_REM, - VALPY_POW + VALPY_POW, + VALPY_LSH, + VALPY_RSH, + VALPY_BITAND, + VALPY_BITOR, + VALPY_BITXOR }; /* If TYPE is a reference, return the target; otherwise return TYPE. */ @@ -244,7 +274,12 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) kind of object, altogether. Because of this, we can't assume self is a gdb.Value object and need to convert it from python as well. */ arg1 = convert_value_from_python (self); + if (arg1 == NULL) + return NULL; + arg2 = convert_value_from_python (other); + if (arg2 == NULL) + return NULL; switch (opcode) { @@ -302,6 +337,21 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) case VALPY_POW: res_val = value_binop (arg1, arg2, BINOP_EXP); break; + case VALPY_LSH: + res_val = value_binop (arg1, arg2, BINOP_LSH); + break; + case VALPY_RSH: + res_val = value_binop (arg1, arg2, BINOP_RSH); + break; + case VALPY_BITAND: + res_val = value_binop (arg1, arg2, BINOP_BITWISE_AND); + break; + case VALPY_BITOR: + res_val = value_binop (arg1, arg2, BINOP_BITWISE_IOR); + break; + case VALPY_BITXOR: + res_val = value_binop (arg1, arg2, BINOP_BITWISE_XOR); + break; } } GDB_PY_HANDLE_EXCEPTION (except); @@ -412,45 +462,66 @@ valpy_nonzero (PyObject *self) } } -/* Implements comparison operations for value objects. */ +/* Implements ~ for value objects. */ static PyObject * -valpy_richcompare (PyObject *self, PyObject *other, int op) +valpy_invert (PyObject *self) { - int result = 0; - struct value *value_self, *value_other; + struct value *val = NULL; volatile struct gdb_exception except; - if (PyObject_TypeCheck (other, &value_object_type)) - value_other = ((value_object *) other)->value; - else if (PyInt_Check (other)) + TRY_CATCH (except, RETURN_MASK_ALL) { - LONGEST l; + val = value_complement (((value_object *) self)->value); + } + GDB_PY_HANDLE_EXCEPTION (except); - l = PyInt_AsLong (other); - if (PyErr_Occurred ()) - return NULL; + return value_to_value_object (val); +} - value_other = value_from_longest (builtin_type_pyint, l); - } - else if (PyFloat_Check (other)) - { - DOUBLEST d; +/* Implements left shift for value objects. */ +static PyObject * +valpy_lsh (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_LSH, self, other); +} - d = PyFloat_AsDouble (other); - if (PyErr_Occurred ()) - return NULL; +/* Implements right shift for value objects. */ +static PyObject * +valpy_rsh (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_RSH, self, other); +} - value_other = value_from_double (builtin_type_pyfloat, d); - } - else if (PyString_Check (other) || PyUnicode_Check (other)) - { - char *str; +/* Implements bitwise and for value objects. */ +static PyObject * +valpy_and (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_BITAND, self, other); +} - str = python_string_to_target_string (other); - value_other = value_from_string (str); - xfree (str); - } - else if (other == Py_None) +/* Implements bitwise or for value objects. */ +static PyObject * +valpy_or (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_BITOR, self, other); +} + +/* Implements bitwise xor for value objects. */ +static PyObject * +valpy_xor (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_BITXOR, self, other); +} + +/* Implements comparison operations for value objects. */ +static PyObject * +valpy_richcompare (PyObject *self, PyObject *other, int op) +{ + int result = 0; + struct value *value_other; + volatile struct gdb_exception except; + + if (other == Py_None) /* Comparing with None is special. From what I can tell, in Python None is smaller than anything else. */ switch (op) { @@ -468,15 +539,13 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) "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) { + value_other = convert_value_from_python (other); + if (value_other == NULL) + return NULL; + switch (op) { case Py_LT: result = value_less (((value_object *) self)->value, value_other); @@ -513,6 +582,92 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) Py_RETURN_FALSE; } +/* Helper function to determine if a type is "int-like". */ +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 + || TYPE_CODE (type) == TYPE_CODE_CHAR + || (ptr_ok && TYPE_CODE (type) == TYPE_CODE_PTR)); +} + +/* Implements conversion to int. */ +static PyObject * +valpy_int (PyObject *self) +{ + struct value *value = ((value_object *) self)->value; + struct type *type = value_type (value); + 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) + { + l = value_as_long (value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return PyInt_FromLong (l); +} + +/* Implements conversion to long. */ +static PyObject * +valpy_long (PyObject *self) +{ + struct value *value = ((value_object *) self)->value; + struct type *type = value_type (value); + 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) + { + l = value_as_long (value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return PyLong_FromLong (l); +} + +/* Implements conversion to float. */ +static PyObject * +valpy_float (PyObject *self) +{ + struct value *value = ((value_object *) self)->value; + struct type *type = value_type (value); + 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) + { + d = value_as_double (value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return PyFloat_FromDouble (d); +} + /* 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 * @@ -533,7 +688,7 @@ value_to_value_object (struct value *val) } /* Try to convert a Python value to a gdb value. If the value cannot - be converted, throw a gdb exception. */ + be converted, set a Python exception and return NULL. */ struct value * convert_value_from_python (PyObject *obj) @@ -541,53 +696,72 @@ convert_value_from_python (PyObject *obj) struct value *value = NULL; /* -Wall */ PyObject *target_str, *unicode_str; struct cleanup *old; + volatile struct gdb_exception except; + int cmp; - if (! obj) - error (_("Internal error while converting Python value.")); + gdb_assert (obj != NULL); - 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)) + TRY_CATCH (except, RETURN_MASK_ALL) { - char *s; + if (PyBool_Check (obj)) + { + cmp = PyObject_IsTrue (obj); + if (cmp >= 0) + value = value_from_longest (builtin_type_pybool, cmp); + } + else if (PyInt_Check (obj)) + { + long l = PyInt_AsLong (obj); - s = python_string_to_target_string (obj); - if (s == NULL) - return NULL; + if (! PyErr_Occurred ()) + value = value_from_longest (builtin_type_pyint, l); + } + else if (PyLong_Check (obj)) + { + LONGEST l = PyLong_AsLongLong (obj); - 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 ()) + value = value_from_longest (builtin_type_pylong, l); + } + else if (PyFloat_Check (obj)) + { + double d = PyFloat_AsDouble (obj); - if (PyErr_Occurred ()) - error (_("Error converting Python value.")); + if (! PyErr_Occurred ()) + value = value_from_double (builtin_type_pyfloat, d); + } + else if (gdbpy_is_string (obj)) + { + char *s; + + s = python_string_to_target_string (obj); + if (s != 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 + PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s"), + PyString_AsString (PyObject_Str (obj))); + } + if (except.reason < 0) + { + PyErr_Format (except.reason == RETURN_QUIT + ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, + "%s", except.message); + return NULL; + } return value; } /* Returns value object in the ARGth position in GDB's history. */ PyObject * -gdbpy_get_value_from_history (PyObject *self, PyObject *args) +gdbpy_history (PyObject *self, PyObject *args) { int i; struct value *res_val = NULL; /* Initialize to appease gcc warning. */ @@ -608,7 +782,6 @@ gdbpy_get_value_from_history (PyObject *self, PyObject *args) void gdbpy_initialize_values (void) { - value_object_type.tp_new = valpy_new; if (PyType_Ready (&value_object_type) < 0) return; @@ -619,6 +792,7 @@ gdbpy_initialize_values (void) } static PyMethodDef value_object_methods[] = { + { "address", valpy_address, METH_NOARGS, "Return the address of the value." }, { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." }, {NULL} /* Sentinel */ }; @@ -634,7 +808,19 @@ static PyNumberMethods value_object_as_number = { valpy_negative, /* nb_negative */ valpy_positive, /* nb_positive */ valpy_absolute, /* nb_absolute */ - valpy_nonzero /* nb_nonzero */ + valpy_nonzero, /* nb_nonzero */ + valpy_invert, /* nb_invert */ + valpy_lsh, /* nb_lshift */ + valpy_rsh, /* nb_rshift */ + valpy_and, /* nb_and */ + valpy_xor, /* nb_xor */ + valpy_or, /* nb_or */ + NULL, /* nb_coerce */ + valpy_int, /* nb_int */ + valpy_long, /* nb_long */ + valpy_float, /* nb_float */ + NULL, /* nb_oct */ + NULL /* nb_hex */ }; static PyMappingMethods value_object_as_mapping = { @@ -672,7 +858,17 @@ PyTypeObject value_object_type = { 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - value_object_methods /* tp_methods */ + value_object_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + valpy_new /* tp_new */ }; #endif /* HAVE_PYTHON */ diff --git a/gdb/python/python.c b/gdb/python/python.c index e778ac4..991321f 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -52,7 +52,7 @@ static PyObject *gdbpy_flush (PyObject *, PyObject *); static PyMethodDef GdbMethods[] = { - { "get_value_from_history", gdbpy_get_value_from_history, METH_VARARGS, + { "history", gdbpy_history, METH_VARARGS, "Get a value from history" }, { "execute", execute_gdb_command, METH_VARARGS, "Execute a gdb command" }, |