py-lazy-string.c revision 1.5
1/* Python interface to lazy strings.
2
3   Copyright (C) 2010-2015 Free Software Foundation, Inc.
4
5   This file is part of GDB.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20#include "defs.h"
21#include "python-internal.h"
22#include "charset.h"
23#include "value.h"
24#include "valprint.h"
25#include "language.h"
26
27typedef struct {
28  PyObject_HEAD
29  /*  Holds the address of the lazy string.  */
30  CORE_ADDR address;
31
32  /*  Holds the encoding that will be applied to the string
33      when the string is printed by GDB.  If the encoding is set
34      to None then GDB will select the most appropriate
35      encoding when the sting is printed.  */
36  char *encoding;
37
38  /* Holds the length of the string in characters.  If the
39     length is -1, then the string will be fetched and encoded up to
40     the first null of appropriate width.  */
41  long length;
42
43  /*  This attribute holds the type that is represented by the lazy
44      string's type.  */
45  struct type *type;
46} lazy_string_object;
47
48extern PyTypeObject lazy_string_object_type
49    CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("lazy_string_object");
50
51static PyObject *
52stpy_get_address (PyObject *self, void *closure)
53{
54  lazy_string_object *self_string = (lazy_string_object *) self;
55
56  return gdb_py_long_from_ulongest (self_string->address);
57}
58
59static PyObject *
60stpy_get_encoding (PyObject *self, void *closure)
61{
62  lazy_string_object *self_string = (lazy_string_object *) self;
63  PyObject *result;
64
65  /* An encoding can be set to NULL by the user, so check before
66     attempting a Python FromString call.  If NULL return Py_None.  */
67  if (self_string->encoding)
68    result = PyString_FromString (self_string->encoding);
69  else
70    {
71      result = Py_None;
72      Py_INCREF (result);
73    }
74
75  return result;
76}
77
78static PyObject *
79stpy_get_length (PyObject *self, void *closure)
80{
81  lazy_string_object *self_string = (lazy_string_object *) self;
82
83  return PyLong_FromLong (self_string->length);
84}
85
86static PyObject *
87stpy_get_type (PyObject *self, void *closure)
88{
89  lazy_string_object *str_obj = (lazy_string_object *) self;
90
91  return type_to_type_object (str_obj->type);
92}
93
94static PyObject *
95stpy_convert_to_value  (PyObject *self, PyObject *args)
96{
97  lazy_string_object *self_string = (lazy_string_object *) self;
98  struct value *val = NULL;
99
100  if (self_string->address == 0)
101    {
102      PyErr_SetString (gdbpy_gdb_memory_error,
103		       _("Cannot create a value from NULL."));
104      return NULL;
105    }
106
107  TRY
108    {
109      val = value_at_lazy (self_string->type, self_string->address);
110    }
111  CATCH (except, RETURN_MASK_ALL)
112    {
113      GDB_PY_HANDLE_EXCEPTION (except);
114    }
115  END_CATCH
116
117  return value_to_value_object (val);
118}
119
120static void
121stpy_dealloc (PyObject *self)
122{
123  lazy_string_object *self_string = (lazy_string_object *) self;
124
125  xfree (self_string->encoding);
126}
127
128PyObject *
129gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
130			   const char *encoding, struct type *type)
131{
132  lazy_string_object *str_obj = NULL;
133
134  if (address == 0 && length != 0)
135    {
136      PyErr_SetString (gdbpy_gdb_memory_error,
137		       _("Cannot create a lazy string with address 0x0, " \
138			 "and a non-zero length."));
139      return NULL;
140    }
141
142  if (!type)
143    {
144      PyErr_SetString (PyExc_RuntimeError,
145		       _("A lazy string's type cannot be NULL."));
146      return NULL;
147    }
148
149  str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type);
150  if (!str_obj)
151    return NULL;
152
153  str_obj->address = address;
154  str_obj->length = length;
155  if (encoding == NULL || !strcmp (encoding, ""))
156    str_obj->encoding = NULL;
157  else
158    str_obj->encoding = xstrdup (encoding);
159  str_obj->type = type;
160
161  return (PyObject *) str_obj;
162}
163
164int
165gdbpy_initialize_lazy_string (void)
166{
167  if (PyType_Ready (&lazy_string_object_type) < 0)
168    return -1;
169
170  Py_INCREF (&lazy_string_object_type);
171  return 0;
172}
173
174/* Determine whether the printer object pointed to by OBJ is a
175   Python lazy string.  */
176int
177gdbpy_is_lazy_string (PyObject *result)
178{
179  return PyObject_TypeCheck (result, &lazy_string_object_type);
180}
181
182/* Extract the parameters from the lazy string object STRING.
183   ENCODING will either be set to NULL, or will be allocated with
184   xmalloc, in which case the callers is responsible for freeing
185   it.  */
186
187void
188gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr,
189			   struct type **str_type,
190			   long *length, char **encoding)
191{
192  lazy_string_object *lazy;
193
194  gdb_assert (gdbpy_is_lazy_string (string));
195
196  lazy = (lazy_string_object *) string;
197
198  *addr = lazy->address;
199  *str_type = lazy->type;
200  *length = lazy->length;
201  *encoding = lazy->encoding ? xstrdup (lazy->encoding) : NULL;
202}
203
204
205
206static PyMethodDef lazy_string_object_methods[] = {
207  { "value", stpy_convert_to_value, METH_NOARGS,
208    "Create a (lazy) value that contains a pointer to the string." },
209  {NULL}  /* Sentinel */
210};
211
212
213static PyGetSetDef lazy_string_object_getset[] = {
214  { "address", stpy_get_address, NULL, "Address of the string.", NULL },
215  { "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL },
216  { "length", stpy_get_length, NULL, "Length of the string.", NULL },
217  { "type", stpy_get_type, NULL, "Type associated with the string.", NULL },
218  { NULL }  /* Sentinel */
219};
220
221PyTypeObject lazy_string_object_type = {
222  PyVarObject_HEAD_INIT (NULL, 0)
223  "gdb.LazyString",	          /*tp_name*/
224  sizeof (lazy_string_object),	  /*tp_basicsize*/
225  0,				  /*tp_itemsize*/
226  stpy_dealloc,                   /*tp_dealloc*/
227  0,				  /*tp_print*/
228  0,				  /*tp_getattr*/
229  0,				  /*tp_setattr*/
230  0,				  /*tp_compare*/
231  0,				  /*tp_repr*/
232  0,				  /*tp_as_number*/
233  0,				  /*tp_as_sequence*/
234  0,				  /*tp_as_mapping*/
235  0,				  /*tp_hash */
236  0,				  /*tp_call*/
237  0,				  /*tp_str*/
238  0,				  /*tp_getattro*/
239  0,				  /*tp_setattro*/
240  0,				  /*tp_as_buffer*/
241  Py_TPFLAGS_DEFAULT,             /*tp_flags*/
242  "GDB lazy string object",	  /* tp_doc */
243  0,				  /* tp_traverse */
244  0,				  /* tp_clear */
245  0,				  /* tp_richcompare */
246  0,				  /* tp_weaklistoffset */
247  0,			          /* tp_iter */
248  0,				  /* tp_iternext */
249  lazy_string_object_methods,	  /* tp_methods */
250  0,				  /* tp_members */
251  lazy_string_object_getset	  /* tp_getset */
252};
253