From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3604 invoked by alias); 16 Sep 2011 15:28:32 -0000 Received: (qmail 3592 invoked by uid 22791); 16 Sep 2011 15:28:27 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from qmta13.westchester.pa.mail.comcast.net (HELO qmta13.westchester.pa.mail.comcast.net) (76.96.59.243) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 16 Sep 2011 15:28:10 +0000 Received: from omta22.westchester.pa.mail.comcast.net ([76.96.62.73]) by qmta13.westchester.pa.mail.comcast.net with comcast id ZSD11h00B1ap0As5DTUANd; Fri, 16 Sep 2011 15:28:10 +0000 Received: from [10.127.238.91] ([65.206.2.68]) by omta22.westchester.pa.mail.comcast.net with comcast id ZTTw1h02G1U2a2h3iTTzmL; Fri, 16 Sep 2011 15:28:08 +0000 Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Apple Message framework v1084) Subject: Re: Python: add field access by name and standard python mapping methods to gdb.Type From: Paul Koning In-Reply-To: Date: Fri, 16 Sep 2011 15:41:00 -0000 Content-Transfer-Encoding: quoted-printable Message-Id: <3A3AF5AE-70E8-43D0-B8CE-DCADFEEF879A@comcast.net> References: To: gdb-patches@sourceware.org, pmuldoon@redhat.com, Eli Zaretskii 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/msg00309.txt.bz2 On Sep 16, 2011, at 2:48 AM, Eli Zaretskii wrote: >> From: Paul Koning >> Date: Thu, 15 Sep 2011 16:38:33 -0400 >> ... >=20 >> +@code{bar} will be a @code{gdb.Field} object; see below under the >> +description of the @code{fields()} method for a description of the >=20 > "@code{fields}", without the parens. If you use the parentheses, it > looks like a call to `fields' with no arguments, which is not what you > want. >=20 > In general, good Texinfo usage and GNU standards frown on the man-page > tradition of using "()" to indicate that the symbol is a function. I made it @code{Type.fields} to match the recent patch that uses explicit c= lass names when referring to methods. On Sep 16, 2011, at 6:45 AM, Phil Muldoon wrote: > Paul Koning writes: >=20 >> The attached proposed patch adds access to struct and enum fields by the= ir name, just as field names can be used on gdb.Value objects. It also add= s the standard Python methods for mappings (dictionary-like objects), so th= at the kind of things that Python programmers would expect to work on objec= ts that can be indexed by name indeed do work. For example, you can iterat= e through the fields, or query if a field name exists.=20=20 >> ... >=20 >> +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 >> + /* getitem returned error, clear the exception status and >> + return the defval instead. */ >> + PyErr_Clear (); >=20 > Given that typy_getitem can raise errors that do not relate directly to > a lookup (the string conversion call in there might indicate some > other conditions, like out of memory, for example), should we only clear > exceptions in some specific case? Yes, that was wrong (and the Python C API book specifically mentions this s= o I should have caught that). Below is an update with the various comments addressed. paul 2011-09-15 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-15 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 16 Sep 2011 15:19:54 -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 16 Sep 2011 15:19:54 -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 { @@ -210,12 +223,70 @@ 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 Python 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 dictionary with some pre-defined keys. */ +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 +301,49 @@ 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 dictionary with + some pre-defined keys. */ +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 dictionary with + some pre-defined keys. */ +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 + dictionary with some pre-defined keys. */ +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 +1094,198 @@ 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 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 +1353,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 +1368,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 +1394,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 +1444,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 +1475,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 +1488,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 +1545,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 16 Sep 2011 15:19:54 -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 16 Sep 2011 15:19:54 -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 16 Sep 2011 15:19:54 -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