Normalize includes to use common/
[deliverable/binutils-gdb.git] / gdb / python / py-lazy-string.c
index 8309527527da83767e0f4e00980de3863b17129d..443aeb7f45b08405470728d3477f70c688d40589 100644 (file)
@@ -1,6 +1,6 @@
 /* Python interface to lazy strings.
 
-   Copyright (C) 2010 Free Software Foundation, Inc.
+   Copyright (C) 2010-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "python-internal.h"
 #include "charset.h"
 #include "value.h"
-#include "exceptions.h"
 #include "valprint.h"
 #include "language.h"
 
 typedef struct {
   PyObject_HEAD
+
   /*  Holds the address of the lazy string.  */
   CORE_ADDR address;
 
@@ -36,23 +36,32 @@ typedef struct {
       encoding when the sting is printed.  */
   char *encoding;
 
-  /* Holds the length of the string in characters.  If the
-     length is -1, then the string will be fetched and encoded up to
-     the first null of appropriate width.  */
+  /* If TYPE is an array: If the length is known, then this value is the
+     array's length, otherwise it is -1.
+     If TYPE is not an array: Then this value represents the string's length.
+     In either case, if the value is -1 then the string will be fetched and
+     encoded up to the first null of appropriate width.  */
   long length;
 
-  /*  This attribute holds the type that is represented by the lazy
-      string's type.  */
-  struct type *type;
+  /* This attribute holds the type of the string.
+     For example if the lazy string was created from a C "char*" then TYPE
+     represents a C "char*".
+     To get the type of the character in the string call
+     stpy_lazy_string_elt_type.
+     This is recorded as a PyObject so that we take advantage of support for
+     preserving the type should its owning objfile go away.  */
+  PyObject *type;
 } lazy_string_object;
 
-static PyTypeObject lazy_string_object_type;
+extern PyTypeObject lazy_string_object_type
+    CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("lazy_string_object");
 
 static PyObject *
 stpy_get_address (PyObject *self, void *closure)
 {
   lazy_string_object *self_string = (lazy_string_object *) self;
-  return PyLong_FromUnsignedLongLong (self_string->address);
+
+  return gdb_py_long_from_ulongest (self_string->address);
 }
 
 static PyObject *
@@ -78,23 +87,67 @@ static PyObject *
 stpy_get_length (PyObject *self, void *closure)
 {
   lazy_string_object *self_string = (lazy_string_object *) self;
+
   return PyLong_FromLong (self_string->length);
 }
 
-PyObject *
+static PyObject *
 stpy_get_type (PyObject *self, void *closure)
 {
   lazy_string_object *str_obj = (lazy_string_object *) self;
-  return type_to_type_object (str_obj->type);
+
+  Py_INCREF (str_obj->type);
+  return str_obj->type;
 }
 
 static PyObject *
-stpy_convert_to_value  (PyObject *self, PyObject *args)
+stpy_convert_to_value (PyObject *self, PyObject *args)
 {
   lazy_string_object *self_string = (lazy_string_object *) self;
-  struct value *val;
+  struct value *val = NULL;
+
+  if (self_string->address == 0)
+    {
+      PyErr_SetString (gdbpy_gdb_memory_error,
+                      _("Cannot create a value from NULL."));
+      return NULL;
+    }
+
+  TRY
+    {
+      struct type *type = type_object_to_type (self_string->type);
+      struct type *realtype;
+
+      gdb_assert (type != NULL);
+      realtype = check_typedef (type);
+      switch (TYPE_CODE (realtype))
+       {
+       case TYPE_CODE_PTR:
+         /* If a length is specified we need to convert this to an array
+            of the specified size.  */
+         if (self_string->length != -1)
+           {
+             /* PR 20786: There's no way to specify an array of length zero.
+                Record a length of [0,-1] which is how Ada does it.  Anything
+                we do is broken, but this is one possible solution.  */
+             type = lookup_array_range_type (TYPE_TARGET_TYPE (realtype),
+                                             0, self_string->length - 1);
+             val = value_at_lazy (type, self_string->address);
+           }
+         else
+           val = value_from_pointer (type, self_string->address);
+         break;
+       default:
+         val = value_at_lazy (type, self_string->address);
+         break;
+       }
+    }
+  CATCH (except, RETURN_MASK_ALL)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+  END_CATCH
 
-  val = value_at_lazy (self_string->type, self_string->address);
   return value_to_value_object (val);
 }
 
@@ -102,29 +155,65 @@ static void
 stpy_dealloc (PyObject *self)
 {
   lazy_string_object *self_string = (lazy_string_object *) self;
+
   xfree (self_string->encoding);
 }
 
+/* Low level routine to create a <gdb.LazyString> object.
+
+   Note: If TYPE is an array, LENGTH either must be -1 (meaning to use the
+   size of the array, which may itself be unknown in which case a length of
+   -1 is still used) or must be the length of the array.  */
+
 PyObject *
 gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
-                          const char *encoding, struct type *type)
+                                const char *encoding, struct type *type)
 {
   lazy_string_object *str_obj = NULL;
+  struct type *realtype;
 
-  if (address == 0)
+  if (length < -1)
     {
-      PyErr_SetString (PyExc_MemoryError,
-                      "Cannot create a lazy string from a GDB-side string.");
+      PyErr_SetString (PyExc_ValueError, _("Invalid length."));
+      return NULL;
+    }
+
+  if (address == 0 && length != 0)
+    {
+      PyErr_SetString (gdbpy_gdb_memory_error,
+                      _("Cannot create a lazy string with address 0x0, " \
+                        "and a non-zero length."));
       return NULL;
     }
 
   if (!type)
     {
       PyErr_SetString (PyExc_RuntimeError,
-                      "A lazy string's type cannot be NULL.");
+                      _("A lazy string's type cannot be NULL."));
       return NULL;
     }
 
+  realtype = check_typedef (type);
+  switch (TYPE_CODE (realtype))
+    {
+    case TYPE_CODE_ARRAY:
+      {
+       LONGEST array_length = -1;
+       LONGEST low_bound, high_bound;
+
+       if (get_array_bounds (realtype, &low_bound, &high_bound))
+         array_length = high_bound - low_bound + 1;
+       if (length == -1)
+         length = array_length;
+       else if (length != array_length)
+         {
+           PyErr_SetString (PyExc_ValueError, _("Invalid length."));
+           return NULL;
+         }
+       break;
+      }
+    }
+
   str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type);
   if (!str_obj)
     return NULL;
@@ -135,18 +224,19 @@ gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
     str_obj->encoding = NULL;
   else
     str_obj->encoding = xstrdup (encoding);
-  str_obj->type = type;
+  str_obj->type = type_to_type_object (type);
 
   return (PyObject *) str_obj;
 }
 
-void
+int
 gdbpy_initialize_lazy_string (void)
 {
   if (PyType_Ready (&lazy_string_object_type) < 0)
-    return;
+    return -1;
 
   Py_INCREF (&lazy_string_object_type);
+  return 0;
 }
 
 /* Determine whether the printer object pointed to by OBJ is a
@@ -157,86 +247,48 @@ gdbpy_is_lazy_string (PyObject *result)
   return PyObject_TypeCheck (result, &lazy_string_object_type);
 }
 
-/* Extract and return the actual string from the lazy string object
-   STRING.  Addtionally, the string type is written to *STR_TYPE, the
-   string length is written to *LENGTH, and the string encoding is
-   written to *ENCODING.  On error, NULL is returned.  The caller is
-   responsible for freeing the returned buffer.  */
-gdb_byte *
-gdbpy_extract_lazy_string (PyObject *string, struct type **str_type,
-                    long *length, char **encoding)
+/* Return the type of a character in lazy string LAZY.  */
+
+static struct type *
+stpy_lazy_string_elt_type (lazy_string_object *lazy)
 {
-  int width;
-  int bytes_read;
-  gdb_byte *buffer = NULL;
-  int errcode = 0;
-  CORE_ADDR addr;
-  struct gdbarch *gdbarch;
-  enum bfd_endian byte_order;
-  PyObject *py_len = NULL, *py_encoding = NULL; 
-  PyObject *py_addr = NULL, *py_type = NULL;
-  volatile struct gdb_exception except;
-
-  py_len = PyObject_GetAttrString (string, "length");
-  py_encoding = PyObject_GetAttrString (string, "encoding");
-  py_addr = PyObject_GetAttrString (string, "address");
-  py_type = PyObject_GetAttrString (string, "type");
-
-  /* A NULL encoding, length, address or type is not ok.  */
-  if (!py_len || !py_encoding || !py_addr || !py_type)
-    goto error;
-
-  *length = PyLong_AsLong (py_len);
-  addr = PyLong_AsUnsignedLongLong (py_addr);
-
-  /* If the user supplies Py_None an encoding, set encoding to NULL.
-     This will trigger the resulting LA_PRINT_CALL to automatically
-     select an encoding.  */
-  if (py_encoding == Py_None)
-    *encoding = NULL;
-  else
-    *encoding = xstrdup (PyString_AsString (py_encoding));
+  struct type *type = type_object_to_type (lazy->type);
+  struct type *realtype;
 
-  *str_type = type_object_to_type (py_type);
-  gdbarch = get_type_arch (*str_type);
-  byte_order = gdbarch_byte_order (gdbarch);
-  width = TYPE_LENGTH (*str_type);
+  gdb_assert (type != NULL);
+  realtype = check_typedef (type);
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  switch (TYPE_CODE (realtype))
     {
-      errcode = read_string (addr, *length, width,
-                            *length, byte_order, &buffer,
-                            &bytes_read);
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_ARRAY:
+      return TYPE_TARGET_TYPE (realtype);
+    default:
+      /* This is done to preserve existing behaviour.  PR 20769.
+        E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type.  */
+      return realtype;
     }
-  if (except.reason < 0)
-    {
-      PyErr_Format (except.reason == RETURN_QUIT                       \
-                   ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,     \
-                   "%s", except.message);                              \
-      goto error;
+}
 
-    }
+/* Extract the parameters from the lazy string object STRING.
+   ENCODING may be set to NULL, if no encoding is found.  */
+
+void
+gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr,
+                          struct type **str_elt_type,
+                          long *length,
+                          gdb::unique_xmalloc_ptr<char> *encoding)
+{
+  lazy_string_object *lazy;
+
+  gdb_assert (gdbpy_is_lazy_string (string));
+
+  lazy = (lazy_string_object *) string;
 
-  if (errcode)
-    goto error;
-
-  *length = bytes_read / width;
-
-  Py_DECREF (py_encoding);
-  Py_DECREF (py_len);
-  Py_DECREF (py_addr);
-  Py_DECREF (py_type);
-  return buffer;
-
- error:
-  Py_XDECREF (py_encoding);
-  Py_XDECREF (py_len);
-  Py_XDECREF (py_addr);
-  Py_XDECREF (py_type);
-  xfree (buffer);
-  *length = 0;
-  *str_type = NULL;
-  return NULL;
+  *addr = lazy->address;
+  *str_elt_type = stpy_lazy_string_elt_type (lazy);
+  *length = lazy->length;
+  encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL);
 }
 
 \f
@@ -248,7 +300,7 @@ static PyMethodDef lazy_string_object_methods[] = {
 };
 
 
-static PyGetSetDef lazy_string_object_getset[] = {
+static gdb_PyGetSetDef lazy_string_object_getset[] = {
   { "address", stpy_get_address, NULL, "Address of the string.", NULL },
   { "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL },
   { "length", stpy_get_length, NULL, "Length of the string.", NULL },
@@ -256,9 +308,8 @@ static PyGetSetDef lazy_string_object_getset[] = {
   { NULL }  /* Sentinel */
 };
 
-static PyTypeObject lazy_string_object_type = {
-  PyObject_HEAD_INIT (NULL)
-  0,                             /*ob_size*/
+PyTypeObject lazy_string_object_type = {
+  PyVarObject_HEAD_INIT (NULL, 0)
   "gdb.LazyString",              /*tp_name*/
   sizeof (lazy_string_object),   /*tp_basicsize*/
   0,                             /*tp_itemsize*/
This page took 0.029517 seconds and 4 git commands to generate.