From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13491 invoked by alias); 26 Sep 2011 16:01:38 -0000 Received: (qmail 13112 invoked by uid 22791); 26 Sep 2011 16:01:16 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from qmta08.emeryville.ca.mail.comcast.net (HELO qmta08.emeryville.ca.mail.comcast.net) (76.96.30.80) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 26 Sep 2011 16:00:38 +0000 Received: from omta17.emeryville.ca.mail.comcast.net ([76.96.30.73]) by qmta08.emeryville.ca.mail.comcast.net with comcast id dSD71h0051afHeLA8U0Y2t; Mon, 26 Sep 2011 16:00:32 +0000 Received: from [10.127.238.91] ([65.206.2.68]) by omta17.emeryville.ca.mail.comcast.net with comcast id dTzv1h01E1U2a2h8dTzxcS; Mon, 26 Sep 2011 16:00:04 +0000 Subject: [RFA] Re: Python: add field access by name and standard python mapping methods to gdb.Type Mime-Version: 1.0 (Apple Message framework v1084) Content-Type: text/plain; charset=us-ascii From: Paul Koning In-Reply-To: Date: Mon, 26 Sep 2011 17:15:00 -0000 Cc: gdb-patches@sourceware.org Content-Transfer-Encoding: quoted-printable Message-Id: References: <3A3AF5AE-70E8-43D0-B8CE-DCADFEEF879A@comcast.net> To: Doug Evans Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-09/txt/msg00446.txt.bz2 On Sep 23, 2011, at 12:33 PM, Doug Evans wrote: > On Fri, Sep 16, 2011 at 8:27 AM, Paul Koning wro= te: >>=20 >> Below is an update with the various comments addressed. >=20 > Hi. This email is for just a couple of formatting nits. >=20 >> 2011-09-15 Paul Koning >>=20 >> * python/py-type.c (make_fielditem, typy_field_names, typy_items, >> typy_length, typy_get, typy_has_key, typy_make_iter, >> typy_iterkeys, typy_iteritems, typy_itervalues, typy_iter, >> typy_iterator_iter, typy_iterator_iternext, >> typy_iterator_dealloc): : New functions to implement standard >> Python mapping methods on gdb.Type object. >> (gdb.TypeIterator): New Python type. >> * python/python-internal.h (gdbpy_iter_kind): New enum. >> * doc/gdb.texinfo (gdb.Type): Document field access by dictionary >> key syntax. >=20 > Technically speaking, the rule is you can't extend a parenthesized name l= ist > over multiple lines. At least that's the rule I've been asked to follow. > I'd like to see some flexibility here, and I'm not asking you change this= here. > Just pointing it out. >=20 >> +/* Helper function for Type standard mapping methods. Returns a >> + Python object for field i of the type. "kind" specifies what to >> + return: the name of the field, a gdb.Field object corresponding to >> + the field, or a tuple consisting of field name and gdb.Field >> + object. */ >> +static PyObject * >> +make_fielditem (struct type *type, int i, enum gdbpy_iter_kind kind) >=20 > For functions the coding standards say to have a blank line between > its comment and definition. > I realize parts of gdb don't follow this rule, but this rule I like :-), > it is documented, and I'd like to not make things worse. >=20 > This needs to be fixed in several places. I've fixed both -- the ChangeLog is now formatted according to an earlier e= xample I see in ChangeLog. Ok to commit? paul 2011-09-26 Paul Koning * python/py-type.c (make_fielditem, typy_field_names, typy_items) (typy_length, typy_get, typy_has_key, typy_make_iter) (typy_iterkeys, typy_iteritems, typy_itervalues, typy_iter) (typy_iterator_iter, typy_iterator_iternext) (typy_iterator_dealloc): : New functions to implement standard Python mapping methods on gdb.Type object. (gdb.TypeIterator): New Python type. * python/python-internal.h (gdbpy_iter_kind): New enum. * doc/gdb.texinfo (gdb.Type): Document field access by dictionary key syntax. 2011-09-26 Paul Koning * gdb.python/py-type.c (enum E): New. * gdb.python/py-type.exp (test_fields): Add tests for Python mapping access to fields. (test_enums): New test for field access on enums. Index: doc/gdb.texinfo =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.862 diff -u -r1.862 gdb.texinfo --- doc/gdb.texinfo 16 Sep 2011 09:07:01 -0000 1.862 +++ doc/gdb.texinfo 26 Sep 2011 15:54:34 -0000 @@ -21537,6 +21537,19 @@ If the named type cannot be found, it will throw an exception. @end defun =20 +If the type is a structure or class type, or an enum type, the fields +of that type can be accessed using the Python @dfn{dictionary syntax}. +For example, if @code{some_type} is a @code{gdb.Type} instance holding +a structure type, you can access its @code{foo} field with: + +@smallexample +bar =3D some_type['foo'] +@end smallexample + +@code{bar} will be a @code{gdb.Field} object; see below under the +description of the @code{Type.fields} method for a description of the +@code{gdb.Field} class. + An instance of @code{Type} has the following attributes: =20 @table @code @@ -21570,7 +21583,7 @@ represented as fields. If the type has no fields, or does not fit into one of these categories, an empty sequence will be returned. =20 -Each field is an object, with some pre-defined attributes: +Each field is a @code{gdb.Field} object, with some pre-defined attributes: @table @code @item bitpos This attribute is not available for @code{static} fields (as in Index: python/py-type.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvs/src/src/gdb/python/py-type.c,v retrieving revision 1.21 diff -u -r1.21 py-type.c --- python/py-type.c 15 Sep 2011 18:33:15 -0000 1.21 +++ python/py-type.c 26 Sep 2011 15:54:34 -0000 @@ -55,6 +55,19 @@ =20 static PyTypeObject field_object_type; =20 +/* A type iterator object. */ +typedef struct { + PyObject_HEAD + /* The current field index. */ + int field; + /* What to return. */ + enum gdbpy_iter_kind kind; + /* Pointer back to the original source type object. */ + struct pyty_type_object *source; +} typy_iterator_object; + +static PyTypeObject type_iterator_object_type; + /* This is used to initialize various gdb.TYPE_ constants. */ struct pyty_code { @@ -137,7 +150,8 @@ } =20 /* Helper function for typy_fields which converts a single field to a - dictionary. Returns NULL on error. */ + gdb.Field object. Returns NULL on error. */ + static PyObject * convert_field (struct type *type, int field) { @@ -210,12 +224,73 @@ return NULL; } =20 -/* Return a sequence of all fields. Each field is a dictionary with - some pre-defined keys. */ +/* Helper function to return the name of a field, as a gdb.Field object. + If the field doesn't have a name, None is returned. */ + static PyObject * -typy_fields (PyObject *self, PyObject *args) +field_name (struct type *type, int field) { PyObject *result; + + if (TYPE_FIELD_NAME (type, field)) + result =3D PyString_FromString (TYPE_FIELD_NAME (type, field)); + else + { + result =3D Py_None; + Py_INCREF (result); + } + return result; +} + +/* Helper function for Type standard mapping methods. Returns a + Python object for field i of the type. "kind" specifies what to + return: the name of the field, a gdb.Field object corresponding to + the field, or a tuple consisting of field name and gdb.Field + object. */ + +static PyObject * +make_fielditem (struct type *type, int i, enum gdbpy_iter_kind kind) +{ + PyObject *item =3D NULL, *key =3D NULL, *value =3D NULL; + + switch (kind) + { + case iter_items: + key =3D field_name (type, i); + if (key =3D=3D NULL) + goto fail; + value =3D convert_field (type, i); + if (value =3D=3D NULL) + goto fail; + item =3D PyTuple_New (2); + if (item =3D=3D NULL) + goto fail; + PyTuple_SET_ITEM (item, 0, key); + PyTuple_SET_ITEM (item, 1, value); + break; + case iter_keys: + item =3D field_name (type, i); + break; + case iter_values: + item =3D convert_field (type, i); + break; + } + return item; +=20=20 + fail: + Py_XDECREF (key); + Py_XDECREF (value); + Py_XDECREF (item); + return NULL; +} + +/* Return a sequence of all field names, fields, or (name, field) pairs. + Each field is a gdb.Field object. */ + +static PyObject * +typy_fields_items (PyObject *self, enum gdbpy_iter_kind kind) +{ + PyObject *result =3D NULL, *item =3D NULL; int i; struct type *type =3D ((type_object *) self)->type; volatile struct gdb_exception except; @@ -230,26 +305,50 @@ then memoize the result (and perhaps make Field.type() lazy). However, that can lead to cycles. */ result =3D PyList_New (0); - + if (result =3D=3D NULL) + return NULL; +=20=20 for (i =3D 0; i < TYPE_NFIELDS (type); ++i) { - PyObject *dict =3D convert_field (type, i); - - if (!dict) - { - Py_DECREF (result); - return NULL; - } - if (PyList_Append (result, dict)) - { - Py_DECREF (dict); - Py_DECREF (result); - return NULL; - } - Py_DECREF (dict); + item =3D make_fielditem (type, i, kind); + if (!item) + goto fail; + if (PyList_Append (result, item)) + goto fail; + Py_DECREF (item); } =20 return result; + + fail: + Py_XDECREF (item); + Py_XDECREF (result); + return NULL; +} + +/* Return a sequence of all fields. Each field is a gdb.Field object. */ + +static PyObject * +typy_fields (PyObject *self, PyObject *args) +{ + return typy_fields_items (self, iter_values); +} + +/* Return a sequence of all field names. Each field is a gdb.Field object= . */ + +static PyObject * +typy_field_names (PyObject *self, PyObject *args) +{ + return typy_fields_items (self, iter_keys); +} + +/* Return a sequence of all (name, fields) pairs. Each field is a=20 + gdb.Field object. */ + +static PyObject * +typy_items (PyObject *self, PyObject *args) +{ + return typy_fields_items (self, iter_items); } =20 /* Return the type's tag, or None. */ @@ -1000,6 +1099,209 @@ type->ob_type->tp_free (type); } =20 +/* Return number of fields ("length" of the field dictionary). */ + +static Py_ssize_t +typy_length (PyObject *self) +{ + struct type *type =3D ((type_object *) self)->type; + + return TYPE_NFIELDS (type); +} + +/* Return a gdb.Field object for the field named by the argument. */ + +static PyObject * +typy_getitem (PyObject *self, PyObject *key) +{ + struct type *type =3D ((type_object *) self)->type; + char *field; + int i; +=20=20 + field =3D python_string_to_host_string (key); + if (field =3D=3D NULL) + return NULL; + + /* We want just fields of this type, not of base types, so instead of=20 + using lookup_struct_elt_type, portions of that function are + copied here. */ + + for (;;) + { + CHECK_TYPEDEF (type); + if (TYPE_CODE (type) !=3D TYPE_CODE_PTR + && TYPE_CODE (type) !=3D TYPE_CODE_REF) + break; + type =3D TYPE_TARGET_TYPE (type); + } + + for (i =3D 0; i < TYPE_NFIELDS (type); i++) + { + char *t_field_name =3D TYPE_FIELD_NAME (type, i); + + if (t_field_name && (strcmp_iw (t_field_name, field) =3D=3D 0)) + { + return convert_field (type, i); + } + } + PyErr_SetObject (PyExc_KeyError, key); + return NULL; +} + +/* Implement the "get" method on the type object. This is the=20 + same as getitem if the key is present, but returns the supplied + default value or None if the key is not found. */ + +static PyObject * +typy_get (PyObject *self, PyObject *args) +{ + PyObject *key, *defval =3D Py_None, *result; +=20=20 + if (!PyArg_UnpackTuple (args, "get", 1, 2, &key, &defval)) + return NULL; +=20=20 + result =3D typy_getitem (self, key); + if (result !=3D NULL) + return result; +=20=20 + /* typy_getitem returned error status. If the exception is + KeyError, clear the exception status and return the defval + instead. Otherwise return the exception unchanged. */ + if (!PyErr_ExceptionMatches (PyExc_KeyError)) + return NULL; +=20=20 + PyErr_Clear (); + Py_INCREF (defval); + return defval; +} + +/* Implement the "has_key" method on the type object. */ + +static PyObject * +typy_has_key (PyObject *self, PyObject *args) +{ + struct type *type =3D ((type_object *) self)->type; + char *field; + int i; +=20=20 + if (!PyArg_ParseTuple (args, "s", &field)) + return NULL; + + /* We want just fields of this type, not of base types, so instead of=20 + using lookup_struct_elt_type, portions of that function are + copied here. */ + + for (;;) + { + CHECK_TYPEDEF (type); + if (TYPE_CODE (type) !=3D TYPE_CODE_PTR + && TYPE_CODE (type) !=3D TYPE_CODE_REF) + break; + type =3D TYPE_TARGET_TYPE (type); + } + + for (i =3D 0; i < TYPE_NFIELDS (type); i++) + { + char *t_field_name =3D TYPE_FIELD_NAME (type, i); + + if (t_field_name && (strcmp_iw (t_field_name, field) =3D=3D 0)) + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; +} + +/* Make an iterator object to iterate over keys, values, or items. */ + +static PyObject * +typy_make_iter (PyObject *self, enum gdbpy_iter_kind kind) +{ + typy_iterator_object *typy_iter_obj; + + typy_iter_obj =3D PyObject_New (typy_iterator_object, + &type_iterator_object_type); + if (typy_iter_obj =3D=3D NULL) + return NULL; + + typy_iter_obj->field =3D 0; + typy_iter_obj->kind =3D kind; + Py_INCREF (self); + typy_iter_obj->source =3D (type_object *) self; + + return (PyObject *) typy_iter_obj; +} + +/* iteritems() method. */ + +static PyObject * +typy_iteritems (PyObject *self, PyObject *args) +{ + return typy_make_iter (self, iter_items); +} + +/* iterkeys() method. */ + +static PyObject * +typy_iterkeys (PyObject *self, PyObject *args) +{ + return typy_make_iter (self, iter_keys); +} + +/* Iterating over the class, same as iterkeys except for the function + signature. */ + +static PyObject * +typy_iter (PyObject *self) +{ + return typy_make_iter (self, iter_keys); +} + +/* itervalues() method. */ + +static PyObject * +typy_itervalues (PyObject *self, PyObject *args) +{ + return typy_make_iter (self, iter_values); +} + +/* Return a reference to the type iterator. */ + +static PyObject * +typy_iterator_iter (PyObject *self) +{ + Py_INCREF (self); + return self; +} + +/* Return the next field in the iteration through the list of fields + of the type. */ + +static PyObject * +typy_iterator_iternext (PyObject *self) +{ + typy_iterator_object *iter_obj =3D (typy_iterator_object *) self; + struct type *type =3D iter_obj->source->type; + int i; + PyObject *result; +=20=20 + if (iter_obj->field < TYPE_NFIELDS (type)) + { + result =3D make_fielditem (type, iter_obj->field, iter_obj->kind); + if (result !=3D NULL) + iter_obj->field++; + return result; + } + + return NULL; +} + +static void +typy_iterator_dealloc (PyObject *obj) +{ + typy_iterator_object *iter_obj =3D (typy_iterator_object *) obj; + + Py_DECREF (iter_obj->source); +} + /* Create a new Type referring to TYPE. */ PyObject * type_to_type_object (struct type *type) @@ -1067,6 +1369,8 @@ return; if (PyType_Ready (&field_object_type) < 0) return; + if (PyType_Ready (&type_iterator_object_type) < 0) + return; =20 for (i =3D 0; pyty_codes[i].name; ++i) { @@ -1080,6 +1384,10 @@ Py_INCREF (&type_object_type); PyModule_AddObject (gdb_module, "Type", (PyObject *) &type_object_type); =20 + Py_INCREF (&type_iterator_object_type); + PyModule_AddObject (gdb_module, "TypeIterator", + (PyObject *) &type_iterator_object_type); + Py_INCREF (&field_object_type); PyModule_AddObject (gdb_module, "Field", (PyObject *) &field_object_type= ); } @@ -1102,13 +1410,35 @@ { "array", typy_array, METH_VARARGS, "array (N) -> Type\n\ Return a type which represents an array of N objects of this type." }, + { "__contains__", typy_has_key, METH_VARARGS, + "T.__contains__(k) -> True if T has a field named k, else False" }, { "const", typy_const, METH_NOARGS, "const () -> Type\n\ Return a const variant of this type." }, { "fields", typy_fields, METH_NOARGS, - "field () -> list\n\ -Return a sequence holding all the fields of this type.\n\ -Each field is a dictionary." }, + "fields () -> list\n\ +Return a list holding all the fields of this type.\n\ +Each field is a gdb.Field object." }, + { "get", typy_get, METH_VARARGS, + "T.get(k[,default]) -> returns field named k in T, if it exists;\n\ +otherwise returns default, if supplied, or None if not." }, + { "has_key", typy_has_key, METH_VARARGS, + "T.has_key(k) -> True if T has a field named k, else False" }, + { "items", typy_items, METH_NOARGS, + "items () -> list\n\ +Return a list of (name, field) pairs of this type.\n\ +Each field is a gdb.Field object." }, + { "iteritems", typy_iteritems, METH_NOARGS, + "iteritems () -> an iterator over the (name, field)\n\ +pairs of this type. Each field is a gdb.Field object." }, + { "iterkeys", typy_iterkeys, METH_NOARGS, + "iterkeys () -> an iterator over the field names of this type." }, + { "itervalues", typy_itervalues, METH_NOARGS, + "itervalues () -> an iterator over the fields of this type.\n\ +Each field is a gdb.Field object." }, + { "keys", typy_field_names, METH_NOARGS, + "keys () -> list\n\ +Return a list holding all the fields names of this type." }, { "pointer", typy_pointer, METH_NOARGS, "pointer () -> Type\n\ Return a type of pointer to this type." }, @@ -1130,12 +1460,22 @@ { "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 () -> list\n\ +Return a list holding all the fields of this type.\n\ +Each field is a gdb.Field object." }, { "volatile", typy_volatile, METH_NOARGS, "volatile () -> Type\n\ Return a volatile variant of this type" }, { NULL } }; =20 +static PyMappingMethods typy_mapping =3D { + typy_length, + typy_getitem, + NULL /* no "set" method */ +}; + static PyTypeObject type_object_type =3D { PyObject_HEAD_INIT (NULL) @@ -1151,7 +1491,7 @@ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ + &typy_mapping, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ typy_str, /*tp_str*/ @@ -1164,7 +1504,7 @@ 0, /* tp_clear */ typy_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ + typy_iter, /* tp_iter */ 0, /* tp_iternext */ type_object_methods, /* tp_methods */ 0, /* tp_members */ @@ -1221,3 +1561,35 @@ 0, /* tp_alloc */ 0, /* tp_new */ }; + +static PyTypeObject type_iterator_object_type =3D { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.TypeIterator", /*tp_name*/ + sizeof (typy_iterator_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + typy_iterator_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB type iterator object", /*tp_doc */ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + typy_iterator_iter, /*tp_iter */ + typy_iterator_iternext, /*tp_iternext */ + 0 /*tp_methods */ +}; Index: python/python-internal.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvs/src/src/gdb/python/python-internal.h,v retrieving revision 1.48 diff -u -r1.48 python-internal.h --- python/python-internal.h 15 Sep 2011 12:42:30 -0000 1.48 +++ python/python-internal.h 26 Sep 2011 15:54:34 -0000 @@ -104,6 +104,8 @@ =20 #include "exceptions.h" =20 +enum gdbpy_iter_kind { iter_keys, iter_values, iter_items }; + struct block; struct value; struct language_defn; Index: testsuite/gdb.python/py-type.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-type.c,v retrieving revision 1.4 diff -u -r1.4 py-type.c --- testsuite/gdb.python/py-type.c 1 Jan 2011 15:33:49 -0000 1.4 +++ testsuite/gdb.python/py-type.c 26 Sep 2011 15:54:34 -0000 @@ -43,6 +43,10 @@ =20 #endif =20 +enum E +{ v1, v2, v3 +}; + int main () { @@ -56,9 +60,12 @@ d.e =3D 3; d.f =3D 4; #endif - + enum E e; +=20=20 st.a =3D 3; st.b =3D 5; =20 + e =3D v2; +=20=20 return 0; /* break to inspect struct and array. */ } Index: testsuite/gdb.python/py-type.exp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-type.exp,v retrieving revision 1.13 diff -u -r1.13 py-type.exp --- testsuite/gdb.python/py-type.exp 26 Jul 2011 18:38:55 -0000 1.13 +++ testsuite/gdb.python/py-type.exp 26 Sep 2011 15:54:34 -0000 @@ -86,6 +86,14 @@ gdb_test "python print fields\[0\].name" "a" "Check structure field a na= me" gdb_test "python print fields\[1\].name" "b" "Check structure field b na= me" =20 + # Test Python mapping behavior of gdb.Type for structs/classes + gdb_test "python print len(st.type)" "2" "Check number of fields" + gdb_test "python print st.type\['a'\].name" "a" "Check fields lookup by = name" + gdb_test "python print \[v.bitpos for v in st.type.itervalues()\]" {\[= 0L, 32L\]} "Check fields iteration over values" + gdb_test "python print \[(n, v.bitpos) for (n, v) in st.type.items()\]= " {\[\('a', 0L\), \('b', 32L\)\]} "Check fields items list" + gdb_test "python print 'a' in st.type" "True" "Check field name exists t= est" + gdb_test "python print 'nosuch' in st.type" "False" "Check field name no= nexists test" +=20=20 # Test regression PR python/10805 gdb_py_test_silent_cmd "print ar" "print value" 1 gdb_py_test_silent_cmd "python ar =3D gdb.history (0)" "get value from = history" 1 @@ -101,6 +109,21 @@ gdb_test "python print ar\[0\].type =3D=3D ar\[0\].type" "True" } =20 +proc test_enums {} { + gdb_py_test_silent_cmd "print e" "print value" 1 + gdb_py_test_silent_cmd "python e =3D gdb.history (0)" "get value from h= istory" 1 + gdb_py_test_silent_cmd "python fields =3D e.type.fields()" "get value fr= om history" 1 + gdb_test "python print len(fields)" "3" "Check the number of enum fields" + gdb_test "python print fields\[0\].name" "v1" "Check enum field name" + gdb_test "python print fields\[1\].name" "v2" "Check enum field name" + + # Ditto but by mapping operations + gdb_test "python print len(e.type)" "3" "Check the number of enum fields" + gdb_test "python print e.type\['v1'\].name" "v1" "Check enum field looku= p by name" + gdb_test "python print e.type\['v3'\].name" "v3" "Check enum field looku= p by name" + gdb_test "python print \[v.bitpos for v in e.type.itervalues()\]" {\[0= L, 1L, 2L\]} "Check num fields iteration over values" + gdb_test "python print \[(n, v.bitpos) for (n, v) in e.type.items()\]"= {\[\('v1', 0L\), \('v2', 1L\), \('v3', 2L\)\]} "Check enum fields items li= st" +} proc test_base_class {} { gdb_py_test_silent_cmd "print d" "print value" 1 gdb_py_test_silent_cmd "python d =3D gdb.history (0)" "get value from h= istory" 1 @@ -169,6 +192,7 @@ =20 runto_bp "break to inspect struct and array." test_fields "c" +test_enums =20 # Perform C++ Tests. build_inferior "${binfile}-cxx" "c++" @@ -178,3 +202,4 @@ test_base_class test_range test_template +test_enums