2012-12-10 Paul Koning <paul_koning@dell.com>
[platform/upstream/binutils.git] / gdb / testsuite / gdb.python / py-prettyprint.py
1 # Copyright (C) 2008-2012 Free Software Foundation, Inc.
2
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 # This file is part of the GDB testsuite.  It tests python pretty
17 # printers.
18
19 import re
20 import gdb
21
22 def _iterator (pointer, len):
23     start = pointer
24     end = pointer + len
25     while pointer != end:
26         if exception_flag:
27             raise gdb.MemoryError ('hi bob')
28         yield ('[%d]' % int (pointer - start), pointer.dereference())
29         pointer += 1
30
31 # Test returning a Value from a printer.
32 class string_print (object):
33     def __init__(self, val):
34         self.val = val
35
36     def to_string(self):
37         return self.val['whybother']['contents']
38
39 # Test a class-based printer.
40 class ContainerPrinter (object):
41
42     def __init__(self, val):
43         self.val = val
44
45     def to_string(self):
46         return 'container %s with %d elements' % (self.val['name'], self.val['len'])
47
48     def children(self):
49         return _iterator(self.val['elements'], self.val['len'])
50
51 # Treats a container as array.
52 class ArrayPrinter:
53     class _iterator:
54         def __init__ (self, pointer, len):
55             self.start = pointer
56             self.pointer = pointer
57             self.end = pointer + len
58
59         def __iter__(self):
60             return self
61
62         def next(self):
63             if self.pointer == self.end:
64                 raise StopIteration
65             result = self.pointer
66             self.pointer = self.pointer + 1
67             return ('[%d]' % int (result - self.start), result.dereference())
68
69     def __init__(self, val):
70         self.val = val
71
72     def to_string(self):
73         return 'array %s with %d elements' % (self.val['name'], self.val['len'])
74
75     def children(self):
76         return self._iterator(self.val['elements'], self.val['len'])
77
78     def display_hint (self):
79         return 'array'
80
81 # Flag to make NoStringContainerPrinter throw an exception.
82 exception_flag = False
83
84 # Test a printer where to_string is None
85 class NoStringContainerPrinter (object):
86     def __init__(self, val):
87         self.val = val
88
89     def to_string(self):
90         return None
91
92     def children(self):
93         return _iterator(self.val['elements'], self.val['len'])
94
95 class pp_s (object):
96     def __init__(self, val):
97         self.val = val
98
99     def to_string(self):
100         a = self.val["a"]
101         b = self.val["b"]
102         if a.address != b:
103             raise Exception("&a(%s) != b(%s)" % (str(a.address), str(b)))
104         return " a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
105
106 class pp_ss (object):
107     def __init__(self, val):
108         self.val = val
109
110     def to_string(self):
111         return "a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
112
113 class pp_sss (object):
114     def __init__(self, val):
115         self.val = val
116
117     def to_string(self):
118         return "a=<" + str(self.val['a']) + "> b=<" + str(self.val["b"]) + ">"
119
120 class pp_multiple_virtual (object):
121     def __init__ (self, val):
122         self.val = val
123
124     def to_string (self):
125         return "pp value variable is: " + str (self.val['value'])
126
127 class pp_vbase1 (object):
128     def __init__ (self, val):
129         self.val = val
130
131     def to_string (self):
132         return "pp class name: " + self.val.type.tag
133
134 class pp_nullstr (object):
135     def __init__(self, val):
136         self.val = val
137
138     def to_string(self):
139         return self.val['s'].string(gdb.target_charset())
140
141 class pp_ns (object):
142     "Print a std::basic_string of some kind"
143
144     def __init__(self, val):
145         self.val = val
146
147     def to_string(self):
148         len = self.val['length']
149         return self.val['null_str'].string (gdb.target_charset(), length = len)
150
151     def display_hint (self):
152         return 'string'
153
154 pp_ls_encoding = None
155
156 class pp_ls (object):
157     "Print a std::basic_string of some kind"
158
159     def __init__(self, val):
160         self.val = val
161
162     def to_string(self):
163         if pp_ls_encoding is not None:
164             return self.val['lazy_str'].lazy_string(encoding = pp_ls_encoding)
165         else:
166             return self.val['lazy_str'].lazy_string()
167
168     def display_hint (self):
169         return 'string'
170
171 class pp_hint_error (object):
172     "Throw error from display_hint"
173
174     def __init__(self, val):
175         self.val = val
176
177     def to_string(self):
178         return 'hint_error_val'
179
180     def display_hint (self):
181         raise Exception("hint failed")
182
183 class pp_children_as_list (object):
184     "Throw error from display_hint"
185
186     def __init__(self, val):
187         self.val = val
188
189     def to_string(self):
190         return 'children_as_list_val'
191
192     def children (self):
193         return [('one', 1)]
194
195 class pp_outer (object):
196     "Print struct outer"
197
198     def __init__ (self, val):
199         self.val = val
200
201     def to_string (self):
202         return "x = %s" % self.val['x']
203
204     def children (self):
205         yield 's', self.val['s']
206         yield 'x', self.val['x']
207
208 class MemoryErrorString (object):
209     "Raise an error"
210
211     def __init__(self, val):
212         self.val = val
213
214     def to_string(self):
215         raise gdb.MemoryError ("Cannot access memory.")
216
217     def display_hint (self):
218         return 'string'
219
220 class pp_eval_type (object):
221     def __init__(self, val):
222         self.val = val
223
224     def to_string(self):
225         gdb.execute("bt", to_string=True)
226         return "eval=<" + str(gdb.parse_and_eval("eval_func (123456789, 2, 3, 4, 5, 6, 7, 8)")) + ">"
227
228 def lookup_function (val):
229     "Look-up and return a pretty-printer that can print val."
230
231     # Get the type.
232     type = val.type
233
234     # If it points to a reference, get the reference.
235     if type.code == gdb.TYPE_CODE_REF:
236         type = type.target ()
237
238     # Get the unqualified type, stripped of typedefs.
239     type = type.unqualified ().strip_typedefs ()
240
241     # Get the type name.    
242     typename = type.tag
243
244     if typename == None:
245         return None
246
247     # Iterate over local dictionary of types to determine
248     # if a printer is registered for that type.  Return an
249     # instantiation of the printer if found.
250     for function in pretty_printers_dict:
251         if function.match (typename):
252             return pretty_printers_dict[function] (val)
253         
254     # Cannot find a pretty printer.  Return None.
255
256     return None
257
258 def disable_lookup_function ():
259     lookup_function.enabled = False
260
261 def enable_lookup_function ():
262     lookup_function.enabled = True
263
264 def register_pretty_printers ():
265     pretty_printers_dict[re.compile ('^struct s$')]   = pp_s
266     pretty_printers_dict[re.compile ('^s$')]   = pp_s
267     pretty_printers_dict[re.compile ('^S$')]   = pp_s
268
269     pretty_printers_dict[re.compile ('^struct ss$')]  = pp_ss
270     pretty_printers_dict[re.compile ('^ss$')]  = pp_ss
271     pretty_printers_dict[re.compile ('^const S &$')]   = pp_s
272     pretty_printers_dict[re.compile ('^SSS$')]  = pp_sss
273     
274     pretty_printers_dict[re.compile ('^VirtualTest$')] =  pp_multiple_virtual
275     pretty_printers_dict[re.compile ('^Vbase1$')] =  pp_vbase1
276
277     pretty_printers_dict[re.compile ('^struct nullstr$')] = pp_nullstr
278     pretty_printers_dict[re.compile ('^nullstr$')] = pp_nullstr
279     
280     # Note that we purposely omit the typedef names here.
281     # Printer lookup is based on canonical name.
282     # However, we do need both tagged and untagged variants, to handle
283     # both the C and C++ cases.
284     pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print
285     pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter
286     pretty_printers_dict[re.compile ('^struct justchildren$')] = NoStringContainerPrinter
287     pretty_printers_dict[re.compile ('^string_repr$')] = string_print
288     pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
289     pretty_printers_dict[re.compile ('^justchildren$')] = NoStringContainerPrinter
290     
291     pretty_printers_dict[re.compile ('^struct ns$')]  = pp_ns
292     pretty_printers_dict[re.compile ('^ns$')]  = pp_ns
293
294     pretty_printers_dict[re.compile ('^struct lazystring$')]  = pp_ls
295     pretty_printers_dict[re.compile ('^lazystring$')]  = pp_ls
296
297     pretty_printers_dict[re.compile ('^struct outerstruct$')]  = pp_outer
298     pretty_printers_dict[re.compile ('^outerstruct$')]  = pp_outer
299
300     pretty_printers_dict[re.compile ('^struct hint_error$')]  = pp_hint_error
301     pretty_printers_dict[re.compile ('^hint_error$')]  = pp_hint_error
302
303     pretty_printers_dict[re.compile ('^struct children_as_list$')]  = pp_children_as_list
304     pretty_printers_dict[re.compile ('^children_as_list$')]  = pp_children_as_list
305
306     pretty_printers_dict[re.compile ('^memory_error$')]  = MemoryErrorString
307
308     pretty_printers_dict[re.compile ('^eval_type_s$')] = pp_eval_type
309
310 pretty_printers_dict = {}
311
312 register_pretty_printers ()
313 gdb.pretty_printers.append (lookup_function)