2010-04-08 Phil Muldoon <pmuldoon@redhat.com>
[external/binutils.git] / gdb / python / py-lazy-string.c
1 /* Python interface to lazy strings.
2
3    Copyright (C) 2010 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 "exceptions.h"
25 #include "valprint.h"
26 #include "language.h"
27
28 typedef struct {
29   PyObject_HEAD
30   /*  Holds the address of the lazy string.  */
31   CORE_ADDR address;
32
33   /*  Holds the encoding that will be applied to the string
34       when the string is printed by GDB.  If the encoding is set
35       to None then GDB will select the most appropriate
36       encoding when the sting is printed.  */
37   char *encoding;
38
39   /* Holds the length of the string in characters.  If the
40      length is -1, then the string will be fetched and encoded up to
41      the first null of appropriate width.  */
42   long length;
43
44   /*  This attribute holds the type that is represented by the lazy
45       string's type.  */
46   struct type *type;
47 } lazy_string_object;
48
49 static PyTypeObject lazy_string_object_type;
50
51 static PyObject *
52 stpy_get_address (PyObject *self, void *closure)
53 {
54   lazy_string_object *self_string = (lazy_string_object *) self;
55   return PyLong_FromUnsignedLongLong (self_string->address);
56 }
57
58 static PyObject *
59 stpy_get_encoding (PyObject *self, void *closure)
60 {
61   lazy_string_object *self_string = (lazy_string_object *) self;
62   PyObject *result;
63
64   /* An encoding can be set to NULL by the user, so check before
65      attempting a Python FromString call.  If NULL return Py_None.  */
66   if (self_string->encoding)
67     result = PyString_FromString (self_string->encoding);
68   else
69     {
70       result = Py_None;
71       Py_INCREF (result);
72     }
73
74   return result;
75 }
76
77 static PyObject *
78 stpy_get_length (PyObject *self, void *closure)
79 {
80   lazy_string_object *self_string = (lazy_string_object *) self;
81   return PyLong_FromLong (self_string->length);
82 }
83
84 PyObject *
85 stpy_get_type (PyObject *self, void *closure)
86 {
87   lazy_string_object *str_obj = (lazy_string_object *) self;
88   return type_to_type_object (str_obj->type);
89 }
90
91 static PyObject *
92 stpy_convert_to_value  (PyObject *self, PyObject *args)
93 {
94   lazy_string_object *self_string = (lazy_string_object *) self;
95   struct value *val;
96
97   if (self_string->address == 0)
98     {
99       PyErr_SetString (PyExc_MemoryError,
100                        _("Cannot create a value from NULL"));
101       return NULL;
102     }
103
104   val = value_at_lazy (self_string->type, self_string->address);
105   return value_to_value_object (val);
106 }
107
108 static void
109 stpy_dealloc (PyObject *self)
110 {
111   lazy_string_object *self_string = (lazy_string_object *) self;
112   xfree (self_string->encoding);
113 }
114
115 PyObject *
116 gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
117                            const char *encoding, struct type *type)
118 {
119   lazy_string_object *str_obj = NULL;
120
121   if (address == 0 && length != 0)
122     {
123       PyErr_SetString (PyExc_MemoryError,
124                        _("Cannot create a lazy string with address 0x0, " \
125                          "and a non-zero length."));
126       return NULL;
127     }
128
129   if (!type)
130     {
131       PyErr_SetString (PyExc_RuntimeError,
132                        "A lazy string's type cannot be NULL.");
133       return NULL;
134     }
135
136   str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type);
137   if (!str_obj)
138     return NULL;
139
140   str_obj->address = address;
141   str_obj->length = length;
142   if (encoding == NULL || !strcmp (encoding, ""))
143     str_obj->encoding = NULL;
144   else
145     str_obj->encoding = xstrdup (encoding);
146   str_obj->type = type;
147
148   return (PyObject *) str_obj;
149 }
150
151 void
152 gdbpy_initialize_lazy_string (void)
153 {
154   if (PyType_Ready (&lazy_string_object_type) < 0)
155     return;
156
157   Py_INCREF (&lazy_string_object_type);
158 }
159
160 /* Determine whether the printer object pointed to by OBJ is a
161    Python lazy string.  */
162 int
163 gdbpy_is_lazy_string (PyObject *result)
164 {
165   return PyObject_TypeCheck (result, &lazy_string_object_type);
166 }
167
168 /* Extract and return the actual string from the lazy string object
169    STRING.  Addtionally, the string type is written to *STR_TYPE, the
170    string length is written to *LENGTH, and the string encoding is
171    written to *ENCODING.  On error, NULL is returned.  The caller is
172    responsible for freeing the returned buffer.  */
173 gdb_byte *
174 gdbpy_extract_lazy_string (PyObject *string, struct type **str_type,
175                      long *length, char **encoding)
176 {
177   int width;
178   int bytes_read;
179   gdb_byte *buffer = NULL;
180   int errcode = 0;
181   CORE_ADDR addr;
182   struct gdbarch *gdbarch;
183   enum bfd_endian byte_order;
184   PyObject *py_len = NULL, *py_encoding = NULL; 
185   PyObject *py_addr = NULL, *py_type = NULL;
186   volatile struct gdb_exception except;
187
188   py_len = PyObject_GetAttrString (string, "length");
189   py_encoding = PyObject_GetAttrString (string, "encoding");
190   py_addr = PyObject_GetAttrString (string, "address");
191   py_type = PyObject_GetAttrString (string, "type");
192
193   /* A NULL encoding, length, address or type is not ok.  */
194   if (!py_len || !py_encoding || !py_addr || !py_type)
195     goto error;
196
197   *length = PyLong_AsLong (py_len);
198   addr = PyLong_AsUnsignedLongLong (py_addr);
199
200   /* If the user supplies Py_None an encoding, set encoding to NULL.
201      This will trigger the resulting LA_PRINT_CALL to automatically
202      select an encoding.  */
203   if (py_encoding == Py_None)
204     *encoding = NULL;
205   else
206     *encoding = xstrdup (PyString_AsString (py_encoding));
207
208   *str_type = type_object_to_type (py_type);
209   gdbarch = get_type_arch (*str_type);
210   byte_order = gdbarch_byte_order (gdbarch);
211   width = TYPE_LENGTH (*str_type);
212
213   TRY_CATCH (except, RETURN_MASK_ALL)
214     {
215       errcode = read_string (addr, *length, width,
216                              *length, byte_order, &buffer,
217                              &bytes_read);
218     }
219   if (except.reason < 0)
220     {
221       PyErr_Format (except.reason == RETURN_QUIT                        \
222                     ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,     \
223                     "%s", except.message);                              \
224       goto error;
225
226     }
227
228   if (errcode)
229     goto error;
230
231   *length = bytes_read / width;
232
233   Py_DECREF (py_encoding);
234   Py_DECREF (py_len);
235   Py_DECREF (py_addr);
236   Py_DECREF (py_type);
237   return buffer;
238
239  error:
240   Py_XDECREF (py_encoding);
241   Py_XDECREF (py_len);
242   Py_XDECREF (py_addr);
243   Py_XDECREF (py_type);
244   xfree (buffer);
245   *length = 0;
246   *str_type = NULL;
247   return NULL;
248 }
249
250 \f
251
252 static PyMethodDef lazy_string_object_methods[] = {
253   { "value", stpy_convert_to_value, METH_NOARGS,
254     "Create a (lazy) value that contains a pointer to the string." },
255   {NULL}  /* Sentinel */
256 };
257
258
259 static PyGetSetDef lazy_string_object_getset[] = {
260   { "address", stpy_get_address, NULL, "Address of the string.", NULL },
261   { "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL },
262   { "length", stpy_get_length, NULL, "Length of the string.", NULL },
263   { "type", stpy_get_type, NULL, "Type associated with the string.", NULL },
264   { NULL }  /* Sentinel */
265 };
266
267 static PyTypeObject lazy_string_object_type = {
268   PyObject_HEAD_INIT (NULL)
269   0,                              /*ob_size*/
270   "gdb.LazyString",               /*tp_name*/
271   sizeof (lazy_string_object),    /*tp_basicsize*/
272   0,                              /*tp_itemsize*/
273   stpy_dealloc,                   /*tp_dealloc*/
274   0,                              /*tp_print*/
275   0,                              /*tp_getattr*/
276   0,                              /*tp_setattr*/
277   0,                              /*tp_compare*/
278   0,                              /*tp_repr*/
279   0,                              /*tp_as_number*/
280   0,                              /*tp_as_sequence*/
281   0,                              /*tp_as_mapping*/
282   0,                              /*tp_hash */
283   0,                              /*tp_call*/
284   0,                              /*tp_str*/
285   0,                              /*tp_getattro*/
286   0,                              /*tp_setattro*/
287   0,                              /*tp_as_buffer*/
288   Py_TPFLAGS_DEFAULT,             /*tp_flags*/
289   "GDB lazy string object",       /* tp_doc */
290   0,                              /* tp_traverse */
291   0,                              /* tp_clear */
292   0,                              /* tp_richcompare */
293   0,                              /* tp_weaklistoffset */
294   0,                              /* tp_iter */
295   0,                              /* tp_iternext */
296   lazy_string_object_methods,     /* tp_methods */
297   0,                              /* tp_members */
298   lazy_string_object_getset       /* tp_getset */
299 };