From 9cc10fd15085bda62b582d484d778f6642483748 Mon Sep 17 00:00:00 2001 From: Paul Koning Date: Tue, 15 Nov 2011 21:17:04 +0000 Subject: [PATCH] * python/py-type.c (typy_get_composite): New function. (typy_nonzero): New function. (typy_values): Rename from typy_fields. (typy_fields): New function. (typy_length): Raise exception if not struct, union, or enum type. (typy_getitem): Ditto. (typy_has_key): Ditto. (typy_make_iter): Ditto. --- gdb/ChangeLog | 11 +++ gdb/python/py-type.c | 155 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 137 insertions(+), 29 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 98f7c7d0db..83282733bf 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2011-11-15 Paul Koning + + * python/py-type.c (typy_get_composite): New function. + (typy_nonzero): New function. + (typy_values): Rename from typy_fields. + (typy_fields): New function. + (typy_length): Raise exception if not struct, union, or enum type. + (typy_getitem): Ditto. + (typy_has_key): Ditto. + (typy_make_iter): Ditto. + 2011-11-15 Doug Evans * NEWS: Mention new parameter basenames-may-differ. diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c index 44a2223282..f76b1c74aa 100644 --- a/gdb/python/py-type.c +++ b/gdb/python/py-type.c @@ -327,11 +327,41 @@ typy_fields_items (PyObject *self, enum gdbpy_iter_kind kind) /* Return a sequence of all fields. Each field is a gdb.Field object. */ static PyObject * -typy_fields (PyObject *self, PyObject *args) +typy_values (PyObject *self, PyObject *args) { return typy_fields_items (self, iter_values); } +/* Return a sequence of all fields. Each field is a gdb.Field object. + This method is similar to typy_values, except where the supplied + gdb.Type is an array, in which case it returns a list of one entry + which is a gdb.Field object for a range (the array bounds). */ + +static PyObject * +typy_fields (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + PyObject *r, *rl; + + if (TYPE_CODE (type) != TYPE_CODE_ARRAY) + return typy_fields_items (self, iter_values); + + /* Array type. Handle this as a special case because the common + machinery wants struct or union or enum types. Build a list of + one entry which is the range for the array. */ + r = convert_field (type, 0); + if (r == NULL) + return NULL; + + rl = Py_BuildValue ("[O]", r); + if (rl == NULL) + { + Py_DECREF (r); + } + + return rl; +} + /* Return a sequence of all field names. Each field is a gdb.Field object. */ static PyObject * @@ -369,6 +399,48 @@ typy_strip_typedefs (PyObject *self, PyObject *args) return type_to_type_object (check_typedef (type)); } +/* Strip typedefs and pointers/reference from a type. Then check that + it is a struct, union, or enum type. If not, raise TypeError. */ + +static struct type * +typy_get_composite (struct type *type) +{ + volatile struct gdb_exception except; + + for (;;) + { + TRY_CATCH (except, RETURN_MASK_ALL) + { + CHECK_TYPEDEF (type); + } + /* Don't use GDB_PY_HANDLE_EXCEPTION here because that returns + a (NULL) pointer of the wrong type. */ + if (except.reason < 0) + { + gdbpy_convert_exception (except); + return NULL; + } + + if (TYPE_CODE (type) != TYPE_CODE_PTR + && TYPE_CODE (type) != TYPE_CODE_REF) + break; + type = TYPE_TARGET_TYPE (type); + } + + /* If this is not a struct, union, or enum type, raise TypeError + exception. */ + if (TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION + && TYPE_CODE (type) != TYPE_CODE_ENUM) + { + PyErr_SetString (PyExc_TypeError, + "Type is not a structure, union, or enum type."); + return NULL; + } + + return type; +} + /* Return an array type. */ static PyObject * @@ -1143,9 +1215,23 @@ typy_length (PyObject *self) { struct type *type = ((type_object *) self)->type; + type = typy_get_composite (type); + if (type == NULL) + return -1; + return TYPE_NFIELDS (type); } +/* Implements boolean evaluation of gdb.Type. Handle this like other + Python objects that don't have a meaningful truth value -- all + values are true. */ + +static int +typy_nonzero (PyObject *self) +{ + return 1; +} + /* Return a gdb.Field object for the field named by the argument. */ static PyObject * @@ -1164,20 +1250,10 @@ typy_getitem (PyObject *self, PyObject *key) using lookup_struct_elt_type, portions of that function are copied here. */ - for (;;) - { - TRY_CATCH (except, RETURN_MASK_ALL) - { - CHECK_TYPEDEF (type); - } - GDB_PY_HANDLE_EXCEPTION (except); - - if (TYPE_CODE (type) != TYPE_CODE_PTR - && TYPE_CODE (type) != TYPE_CODE_REF) - break; - type = TYPE_TARGET_TYPE (type); - } - + type = typy_get_composite (type); + if (type == NULL) + return NULL; + for (i = 0; i < TYPE_NFIELDS (type); i++) { char *t_field_name = TYPE_FIELD_NAME (type, i); @@ -1235,18 +1311,9 @@ typy_has_key (PyObject *self, PyObject *args) using lookup_struct_elt_type, portions of that function are copied here. */ - for (;;) - { - TRY_CATCH (except, RETURN_MASK_ALL) - { - CHECK_TYPEDEF (type); - } - GDB_PY_HANDLE_EXCEPTION (except); - if (TYPE_CODE (type) != TYPE_CODE_PTR - && TYPE_CODE (type) != TYPE_CODE_REF) - break; - type = TYPE_TARGET_TYPE (type); - } + type = typy_get_composite (type); + if (type == NULL) + return NULL; for (i = 0; i < TYPE_NFIELDS (type); i++) { @@ -1265,6 +1332,10 @@ typy_make_iter (PyObject *self, enum gdbpy_iter_kind kind) { typy_iterator_object *typy_iter_obj; + /* Check that "self" is a structure or union type. */ + if (typy_get_composite (((type_object *) self)->type) == NULL) + return NULL; + typy_iter_obj = PyObject_New (typy_iterator_object, &type_iterator_object_type); if (typy_iter_obj == NULL) @@ -1508,7 +1579,7 @@ Return the type of a template argument." }, { "unqualified", typy_unqualified, METH_NOARGS, "unqualified () -> Type\n\ Return a variant of this type without const or volatile attributes." }, - { "values", typy_fields, METH_NOARGS, + { "values", typy_values, METH_NOARGS, "values () -> list\n\ Return a list holding all the fields of this type.\n\ Each field is a gdb.Field object." }, @@ -1518,6 +1589,32 @@ Return a volatile variant of this type" }, { NULL } }; +static PyNumberMethods type_object_as_number = { + NULL, /* nb_add */ + NULL, /* nb_subtract */ + NULL, /* nb_multiply */ + NULL, /* nb_divide */ + NULL, /* nb_remainder */ + NULL, /* nb_divmod */ + NULL, /* nb_power */ + NULL, /* nb_negative */ + NULL, /* nb_positive */ + NULL, /* nb_absolute */ + typy_nonzero, /* nb_nonzero */ + NULL, /* nb_invert */ + NULL, /* nb_lshift */ + NULL, /* nb_rshift */ + NULL, /* nb_and */ + NULL, /* nb_xor */ + NULL, /* nb_or */ + NULL, /* nb_coerce */ + NULL, /* nb_int */ + NULL, /* nb_long */ + NULL, /* nb_float */ + NULL, /* nb_oct */ + NULL /* nb_hex */ +}; + static PyMappingMethods typy_mapping = { typy_length, typy_getitem, @@ -1537,7 +1634,7 @@ static PyTypeObject type_object_type = 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ - 0, /*tp_as_number*/ + &type_object_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ &typy_mapping, /*tp_as_mapping*/ 0, /*tp_hash */