* python/py-type.c (convert_field): Use gdb_py_long_from_longest
[deliverable/binutils-gdb.git] / gdb / python / py-type.c
index 29b2629c274fb18615bc5459bfe179539e467e80..a02402ef02ba4443e76e260d9ba855ca297b29bf 100644 (file)
@@ -1,6 +1,6 @@
 /* Python interface to types.
 
-   Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2008-2012 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -29,6 +29,7 @@
 #include "language.h"
 #include "vec.h"
 #include "bcache.h"
+#include "dwarf2loc.h"
 
 typedef struct pyty_type_object
 {
@@ -55,6 +56,19 @@ typedef struct pyty_field_object
 
 static PyTypeObject field_object_type;
 
+/* 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
 {
@@ -64,6 +78,9 @@ struct pyty_code
   const char *name;
 };
 
+/* Forward declarations.  */
+static PyObject *typy_make_iter (PyObject *self, enum gdbpy_iter_kind kind);
+
 #define ENTRY(X) { X, #X }
 
 static struct pyty_code pyty_codes[] =
@@ -137,7 +154,8 @@ typy_get_code (PyObject *self, void *closure)
 }
 
 /* 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)
 {
@@ -149,11 +167,24 @@ convert_field (struct type *type, int field)
 
   if (!field_is_static (&TYPE_FIELD (type, field)))
     {
-      arg = PyLong_FromLong (TYPE_FIELD_BITPOS (type, field));
+      const char *attrstring;
+
+      if (TYPE_CODE (type) == TYPE_CODE_ENUM)
+       {
+         arg = gdb_py_long_from_longest (TYPE_FIELD_ENUMVAL (type, field));
+         attrstring = "enumval";
+       }
+      else
+       {
+         arg = gdb_py_long_from_longest (TYPE_FIELD_BITPOS (type, field));
+         attrstring = "bitpos";
+       }
+
       if (!arg)
        goto fail;
 
-      if (PyObject_SetAttrString (result, "bitpos", arg) < 0)
+      /* At least python-2.4 had the second parameter non-const.  */
+      if (PyObject_SetAttrString (result, (char *) attrstring, arg) < 0)
        goto failarg;
     }
 
@@ -210,48 +241,157 @@ convert_field (struct type *type, int field)
   return NULL;
 }
 
-/* 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;
-  int i;
-  struct type *type = ((type_object *) self)->type;
+
+  if (TYPE_FIELD_NAME (type, field))
+    result = PyString_FromString (TYPE_FIELD_NAME (type, field));
+  else
+    {
+      result = 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 = NULL, *key = NULL, *value = NULL;
+
+  switch (kind)
+    {
+    case iter_items:
+      key = field_name (type, i);
+      if (key == NULL)
+       goto fail;
+      value = convert_field (type, i);
+      if (value == NULL)
+       goto fail;
+      item = PyTuple_New (2);
+      if (item == NULL)
+       goto fail;
+      PyTuple_SET_ITEM (item, 0, key);
+      PyTuple_SET_ITEM (item, 1, value);
+      break;
+    case iter_keys:
+      item = field_name (type, i);
+      break;
+    case iter_values:
+      item =  convert_field (type, i);
+      break;
+    }
+  return item;
+  
+ 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 *py_type = self;
+  PyObject *result = NULL, *iter = NULL;
   volatile struct gdb_exception except;
+  struct type *type = ((type_object *) py_type)->type;
+  struct type *checked_type = type;
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
-      CHECK_TYPEDEF (type);
+      CHECK_TYPEDEF (checked_type);
     }
   GDB_PY_HANDLE_EXCEPTION (except);
 
-  /* We would like to make a tuple here, make fields immutable, and
-     then memoize the result (and perhaps make Field.type() lazy).
-     However, that can lead to cycles.  */
-  result = PyList_New (0);
-
-  for (i = 0; i < TYPE_NFIELDS (type); ++i)
+  if (checked_type != type)
+    py_type = type_to_type_object (checked_type);
+  iter = typy_make_iter (py_type, kind);
+  if (checked_type != type)
     {
-      PyObject *dict = 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);
+      /* Need to wrap this in braces because Py_DECREF isn't wrapped
+        in a do{}while(0).  */
+      Py_DECREF (py_type);
+    }
+  if (iter != NULL)
+    {
+      result = PySequence_List (iter);
+      Py_DECREF (iter);
     }
 
   return result;
 }
 
+/* Return a sequence of all fields.  Each field is a gdb.Field object.  */
+
+static PyObject *
+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 *
+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 
+   gdb.Field object.  */
+
+static PyObject *
+typy_items (PyObject *self, PyObject *args)
+{
+  return typy_fields_items (self, iter_items);
+}
+
 /* Return the type's tag, or None.  */
 static PyObject *
 typy_get_tag (PyObject *self, void *closure)
@@ -268,10 +408,59 @@ static PyObject *
 typy_strip_typedefs (PyObject *self, PyObject *args)
 {
   struct type *type = ((type_object *) self)->type;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      type = check_typedef (type);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
 
   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 *
@@ -494,11 +683,11 @@ typy_get_sizeof (PyObject *self, void *closure)
     }
   /* Ignore exceptions.  */
 
-  return PyLong_FromLong (TYPE_LENGTH (type));
+  return gdb_py_long_from_longest (TYPE_LENGTH (type));
 }
 
 static struct type *
-typy_lookup_typename (const char *type_name, struct block *block)
+typy_lookup_typename (const char *type_name, const struct block *block)
 {
   struct type *type = NULL;
   volatile struct gdb_exception except;
@@ -517,9 +706,7 @@ typy_lookup_typename (const char *type_name, struct block *block)
     }
   if (except.reason < 0)
     {
-      PyErr_Format (except.reason == RETURN_QUIT
-                   ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
-                   "%s", except.message);
+      gdbpy_convert_exception (except);
       return NULL;
     }
 
@@ -528,11 +715,12 @@ typy_lookup_typename (const char *type_name, struct block *block)
 
 static struct type *
 typy_lookup_type (struct demangle_component *demangled,
-                 struct block *block)
+                 const struct block *block)
 {
-  struct type *type;
-  char *type_name;
+  struct type *type, *rtype = NULL;
+  char *type_name = NULL;
   enum demangle_component_type demangled_type;
+  volatile struct gdb_exception except;
 
   /* Save the type: typy_lookup_type() may (indirectly) overwrite
      memory pointed by demangled.  */
@@ -547,19 +735,41 @@ typy_lookup_type (struct demangle_component *demangled,
       if (! type)
        return NULL;
 
-      switch (demangled_type)
+      TRY_CATCH (except, RETURN_MASK_ALL)
+       {
+         /* If the demangled_type matches with one of the types
+            below, run the corresponding function and save the type
+            to return later.  We cannot just return here as we are in
+            an exception handler.  */
+         switch (demangled_type)
+           {
+           case DEMANGLE_COMPONENT_REFERENCE:
+             rtype =  lookup_reference_type (type);
+             break;
+           case DEMANGLE_COMPONENT_POINTER:
+             rtype = lookup_pointer_type (type);
+             break;
+           case DEMANGLE_COMPONENT_CONST:
+             rtype = make_cv_type (1, 0, type, NULL);
+             break;
+           case DEMANGLE_COMPONENT_VOLATILE:
+             rtype = make_cv_type (0, 1, type, NULL);
+             break;
+           }
+       }
+      if (except.reason < 0)
        {
-       case DEMANGLE_COMPONENT_REFERENCE:
-         return lookup_reference_type (type);
-       case DEMANGLE_COMPONENT_POINTER:
-         return lookup_pointer_type (type);
-       case DEMANGLE_COMPONENT_CONST:
-         return make_cv_type (1, 0, type, NULL);
-       case DEMANGLE_COMPONENT_VOLATILE:
-         return make_cv_type (0, 1, type, NULL);
+         gdbpy_convert_exception (except);
+         return NULL;
        }
     }
-
+  
+  /* If we have a type from the switch statement above, just return
+     that.  */
+  if (rtype)
+    return rtype;
+  
+  /* We don't have a type, so lookup the type.  */
   type_name = cp_comp_to_string (demangled, 10);
   type = typy_lookup_typename (type_name, block);
   xfree (type_name);
@@ -573,15 +783,16 @@ typy_lookup_type (struct demangle_component *demangled,
    versions of GCC, that do not emit DW_TAG_template_*.  */
 
 static PyObject *
-typy_legacy_template_argument (struct type *type, struct block *block,
+typy_legacy_template_argument (struct type *type, const struct block *block,
                               int argno)
 {
   int i;
   struct demangle_component *demangled;
-  struct demangle_parse_info *info;
+  struct demangle_parse_info *info = NULL;
   const char *err;
   struct type *argtype;
   struct cleanup *cleanup;
+  volatile struct gdb_exception except;
 
   if (TYPE_NAME (type) == NULL)
     {
@@ -589,8 +800,13 @@ typy_legacy_template_argument (struct type *type, struct block *block,
       return NULL;
     }
 
-  /* Note -- this is not thread-safe.  */
-  info = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      /* Note -- this is not thread-safe.  */
+      info = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
   if (! info)
     {
       PyErr_SetString (PyExc_RuntimeError, err);
@@ -638,7 +854,7 @@ typy_template_argument (PyObject *self, PyObject *args)
 {
   int argno;
   struct type *type = ((type_object *) self)->type;
-  struct block *block = NULL;
+  const struct block *block = NULL;
   PyObject *block_obj = NULL;
   struct symbol *sym;
   struct value *val = NULL;
@@ -744,7 +960,7 @@ DEF_VEC_O (type_equality_entry_d);
    the same, 0 otherwise.  Handles NULLs properly.  */
 
 static int
-compare_strings (const char *s, const char *t)
+compare_maybe_null_strings (const char *s, const char *t)
 {
   if (s == NULL && t != NULL)
     return 0;
@@ -780,9 +996,10 @@ check_types_equal (struct type *type1, struct type *type2,
       || TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2))
     return Py_NE;
 
-  if (!compare_strings (TYPE_TAG_NAME (type1), TYPE_TAG_NAME (type2)))
+  if (!compare_maybe_null_strings (TYPE_TAG_NAME (type1),
+                                  TYPE_TAG_NAME (type2)))
     return Py_NE;
-  if (!compare_strings (TYPE_NAME (type1), TYPE_NAME (type2)))
+  if (!compare_maybe_null_strings (TYPE_NAME (type1), TYPE_NAME (type2)))
     return Py_NE;
 
   if (TYPE_CODE (type1) == TYPE_CODE_RANGE)
@@ -805,7 +1022,8 @@ check_types_equal (struct type *type1, struct type *type2,
              || FIELD_BITSIZE (*field1) != FIELD_BITSIZE (*field2)
              || FIELD_LOC_KIND (*field1) != FIELD_LOC_KIND (*field2))
            return Py_NE;
-         if (!compare_strings (FIELD_NAME (*field1), FIELD_NAME (*field2)))
+         if (!compare_maybe_null_strings (FIELD_NAME (*field1),
+                                          FIELD_NAME (*field2)))
            return Py_NE;
          switch (FIELD_LOC_KIND (*field1))
            {
@@ -813,16 +1031,36 @@ check_types_equal (struct type *type1, struct type *type2,
              if (FIELD_BITPOS (*field1) != FIELD_BITPOS (*field2))
                return Py_NE;
              break;
+           case FIELD_LOC_KIND_ENUMVAL:
+             if (FIELD_ENUMVAL (*field1) != FIELD_ENUMVAL (*field2))
+               return Py_NE;
+             break;
            case FIELD_LOC_KIND_PHYSADDR:
              if (FIELD_STATIC_PHYSADDR (*field1)
                  != FIELD_STATIC_PHYSADDR (*field2))
                return Py_NE;
              break;
            case FIELD_LOC_KIND_PHYSNAME:
-             if (!compare_strings (FIELD_STATIC_PHYSNAME (*field1),
-                                   FIELD_STATIC_PHYSNAME (*field2)))
+             if (!compare_maybe_null_strings (FIELD_STATIC_PHYSNAME (*field1),
+                                              FIELD_STATIC_PHYSNAME (*field2)))
+               return Py_NE;
+             break;
+           case FIELD_LOC_KIND_DWARF_BLOCK:
+             {
+               struct dwarf2_locexpr_baton *block1, *block2;
+
+               block1 = FIELD_DWARF_BLOCK (*field1);
+               block2 = FIELD_DWARF_BLOCK (*field2);
+               if (block1->per_cu != block2->per_cu
+                   || block1->size != block2->size
+                   || memcmp (block1->data, block2->data, block1->size) != 0)
                return Py_NE;
+             }
              break;
+           default:
+             internal_error (__FILE__, __LINE__, _("Unsupported field kind "
+                                                   "%d by check_types_equal"),
+                             FIELD_LOC_KIND (*field1));
            }
 
          entry.type1 = FIELD_TYPE (*field1);
@@ -834,7 +1072,6 @@ check_types_equal (struct type *type1, struct type *type2,
   if (TYPE_TARGET_TYPE (type1) != NULL)
     {
       struct type_equality_entry entry;
-      int added;
 
       if (TYPE_TARGET_TYPE (type2) == NULL)
        return Py_NE;
@@ -913,11 +1150,13 @@ typy_richcompare (PyObject *self, PyObject *other, int op)
        {
          result = check_types_worklist (&worklist, cache);
        }
-      if (except.reason < 0)
-       result = Py_NE;
-
+      /* check_types_worklist calls several nested Python helper
+        functions, some of which can raise a GDB Exception, so we
+        just check and convert here.  If there is a GDB exception, a
+        comparison is not capable (or trusted), so exit.  */
       bcache_xfree (cache);
       VEC_free (type_equality_entry_d, worklist);
+      GDB_PY_HANDLE_EXCEPTION (except);
     }
 
   if (op == result)
@@ -1000,6 +1239,216 @@ typy_dealloc (PyObject *obj)
   type->ob_type->tp_free (type);
 }
 
+/* Return number of fields ("length" of the field dictionary).  */
+
+static Py_ssize_t
+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 *
+typy_getitem (PyObject *self, PyObject *key)
+{
+  struct type *type = ((type_object *) self)->type;
+  char *field;
+  int i;
+
+  field = python_string_to_host_string (key);
+  if (field == NULL)
+    return NULL;
+
+  /* We want just fields of this type, not of base types, so instead of 
+     using lookup_struct_elt_type, portions of that function are
+     copied here.  */
+
+  type = typy_get_composite (type);
+  if (type == NULL)
+    return NULL;
+  
+  for (i = 0; i < TYPE_NFIELDS (type); i++)
+    {
+      const char *t_field_name = TYPE_FIELD_NAME (type, i);
+
+      if (t_field_name && (strcmp_iw (t_field_name, field) == 0))
+       {
+         return convert_field (type, i);
+       }
+    }
+  PyErr_SetObject (PyExc_KeyError, key);
+  return NULL;
+}
+
+/* Implement the "get" method on the type object.  This is the 
+   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 = Py_None, *result;
+  
+  if (!PyArg_UnpackTuple (args, "get", 1, 2, &key, &defval))
+    return NULL;
+  
+  result = typy_getitem (self, key);
+  if (result != NULL)
+    return result;
+  
+  /* 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;
+  
+  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 = ((type_object *) self)->type;
+  const char *field;
+  int i;
+
+  if (!PyArg_ParseTuple (args, "s", &field))
+    return NULL;
+
+  /* We want just fields of this type, not of base types, so instead of 
+     using lookup_struct_elt_type, portions of that function are
+     copied here.  */
+
+  type = typy_get_composite (type);
+  if (type == NULL)
+    return NULL;
+
+  for (i = 0; i < TYPE_NFIELDS (type); i++)
+    {
+      const char *t_field_name = TYPE_FIELD_NAME (type, i);
+
+      if (t_field_name && (strcmp_iw (t_field_name, field) == 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;
+
+  /* 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)
+      return NULL;
+
+  typy_iter_obj->field = 0;
+  typy_iter_obj->kind = kind;
+  Py_INCREF (self);
+  typy_iter_obj->source = (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 = (typy_iterator_object *) self;
+  struct type *type = iter_obj->source->type;
+  PyObject *result;
+  
+  if (iter_obj->field < TYPE_NFIELDS (type))
+    {
+      result = make_fielditem (type, iter_obj->field, iter_obj->kind);
+      if (result != NULL)
+       iter_obj->field++;
+      return result;
+    }
+
+  return NULL;
+}
+
+static void
+typy_iterator_dealloc (PyObject *obj)
+{
+  typy_iterator_object *iter_obj = (typy_iterator_object *) obj;
+
+  Py_DECREF (iter_obj->source);
+}
+
 /* Create a new Type referring to TYPE.  */
 PyObject *
 type_to_type_object (struct type *type)
@@ -1031,7 +1480,7 @@ gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
   const char *type_name = NULL;
   struct type *type = NULL;
   PyObject *block_obj = NULL;
-  struct block *block = NULL;
+  const struct block *block = NULL;
 
   if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O", keywords,
                                     &type_name, &block_obj))
@@ -1067,6 +1516,8 @@ gdbpy_initialize_types (void)
     return;
   if (PyType_Ready (&field_object_type) < 0)
     return;
+  if (PyType_Ready (&type_iterator_object_type) < 0)
+    return;
 
   for (i = 0; pyty_codes[i].name; ++i)
     {
@@ -1080,6 +1531,10 @@ gdbpy_initialize_types (void)
   Py_INCREF (&type_object_type);
   PyModule_AddObject (gdb_module, "Type", (PyObject *) &type_object_type);
 
+  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);
 }
@@ -1100,15 +1555,39 @@ static PyGetSetDef type_object_getset[] =
 static PyMethodDef type_object_methods[] =
 {
   { "array", typy_array, METH_VARARGS,
-    "array (N) -> Type\n\
-Return a type which represents an array of N objects of this type." },
+    "array ([LOW_BOUND,] HIGH_BOUND) -> Type\n\
+Return a type which represents an array of objects of this type.\n\
+The bounds of the array are [LOW_BOUND, HIGH_BOUND] inclusive.\n\
+If LOW_BOUND is omitted, a value of zero is used." },
+   { "__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 +1609,48 @@ 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_values, 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 }
 };
 
+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,
+  NULL                           /* no "set" method */
+};
+
 static PyTypeObject type_object_type =
 {
   PyObject_HEAD_INIT (NULL)
@@ -1149,9 +1664,9 @@ 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*/
-  0,                             /*tp_as_mapping*/
+  &typy_mapping,                 /*tp_as_mapping*/
   0,                             /*tp_hash */
   0,                             /*tp_call*/
   typy_str,                      /*tp_str*/
@@ -1164,7 +1679,7 @@ static PyTypeObject type_object_type =
   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 */
@@ -1179,6 +1694,13 @@ static PyTypeObject type_object_type =
   0,                             /* tp_new */
 };
 
+static PyGetSetDef field_object_getset[] =
+{
+  { "__dict__", gdb_py_generic_dict, NULL,
+    "The __dict__ for this field.", &field_object_type },
+  { NULL }
+};
+
 static PyTypeObject field_object_type =
 {
   PyObject_HEAD_INIT (NULL)
@@ -1211,7 +1733,7 @@ static PyTypeObject field_object_type =
   0,                             /* tp_iternext */
   0,                             /* tp_methods */
   0,                             /* tp_members */
-  0,                             /* tp_getset */
+  field_object_getset,           /* tp_getset */
   0,                             /* tp_base */
   0,                             /* tp_dict */
   0,                             /* tp_descr_get */
@@ -1221,3 +1743,35 @@ static PyTypeObject field_object_type =
   0,                             /* tp_alloc */
   0,                             /* tp_new */
 };
+
+static PyTypeObject type_iterator_object_type = {
+  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 */
+};
This page took 0.035009 seconds and 4 git commands to generate.