* python/py-type.c (typy_get_composite): New function.
[deliverable/binutils-gdb.git] / gdb / python / py-type.c
index 44a22232827bc55ae7b0b75f392ef096cc66e32c..f76b1c74aa179e2fd0042521ea9da519c060f3e6 100644 (file)
@@ -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 */
This page took 0.02534 seconds and 4 git commands to generate.