]> Git Repo - binutils.git/blob - gdb/testsuite/gdb.python/py-prettyprint.py
43727f7231d0c46255e91eb226c6115fe3d3e5cc
[binutils.git] / gdb / testsuite / gdb.python / py-prettyprint.py
1 # Copyright (C) 2008-2019 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         yield ('[%d]' % int (pointer - start), pointer.dereference())
27         pointer += 1
28
29 # Same as _iterator but can be told to raise an exception.
30 def _iterator_except (pointer, len):
31     start = pointer
32     end = pointer + len
33     while pointer != end:
34         if exception_flag:
35             raise gdb.MemoryError ('hi bob')
36         yield ('[%d]' % int (pointer - start), pointer.dereference())
37         pointer += 1
38
39 # Test returning a Value from a printer.
40 class string_print (object):
41     def __init__(self, val):
42         self.val = val
43
44     def to_string(self):
45         return self.val['whybother']['contents']
46
47 # Test a class-based printer.
48 class ContainerPrinter (object):
49
50     def __init__(self, val):
51         self.val = val
52
53     def to_string(self):
54         return 'container %s with %d elements' % (self.val['name'], self.val['len'])
55
56     def children(self):
57         return _iterator(self.val['elements'], self.val['len'])
58
59     def display_hint (self):
60         if (self.val['is_map_p']):
61             return 'map'
62         else:
63             return None
64
65 # Treats a container as array.
66 class ArrayPrinter (object):
67     def __init__(self, val):
68         self.val = val
69
70     def to_string(self):
71         return 'array %s with %d elements' % (self.val['name'], self.val['len'])
72
73     def children(self):
74         return _iterator(self.val['elements'], self.val['len'])
75
76     def display_hint (self):
77         return 'array'
78
79 # Flag to make NoStringContainerPrinter throw an exception.
80 exception_flag = False
81
82 # Test a printer where to_string is None
83 class NoStringContainerPrinter (object):
84     def __init__(self, val):
85         self.val = val
86
87     def to_string(self):
88         return None
89
90     def children(self):
91         return _iterator_except (self.val['elements'], self.val['len'])
92
93 # See ToStringReturnsValueWrapper.
94 class ToStringReturnsValueInner:
95
96     def __init__(self, val):
97         self.val = val
98
99     def to_string(self):
100         return 'Inner to_string {}'.format(int(self.val['val']))
101
102 # Test a printer that returns a gdb.Value in its to_string.  That gdb.Value
103 # also has its own pretty-printer.
104 class ToStringReturnsValueWrapper:
105
106     def __init__(self, val):
107         self.val = val
108
109     def to_string(self):
110         return self.val['inner']
111
112 class pp_s (object):
113     def __init__(self, val):
114         self.val = val
115
116     def to_string(self):
117         a = self.val["a"]
118         b = self.val["b"]
119         if a.address != b:
120             raise Exception("&a(%s) != b(%s)" % (str(a.address), str(b)))
121         return " a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
122
123 class pp_ss (object):
124     def __init__(self, val):
125         self.val = val
126
127     def to_string(self):
128         return "a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
129
130 class pp_sss (object):
131     def __init__(self, val):
132         self.val = val
133
134     def to_string(self):
135         return "a=<" + str(self.val['a']) + "> b=<" + str(self.val["b"]) + ">"
136
137 class pp_multiple_virtual (object):
138     def __init__ (self, val):
139         self.val = val
140
141     def to_string (self):
142         return "pp value variable is: " + str (self.val['value'])
143
144 class pp_vbase1 (object):
145     def __init__ (self, val):
146         self.val = val
147
148     def to_string (self):
149         return "pp class name: " + self.val.type.tag
150
151 class pp_nullstr (object):
152     def __init__(self, val):
153         self.val = val
154
155     def to_string(self):
156         return self.val['s'].string(gdb.target_charset())
157
158 class pp_ns (object):
159     "Print a std::basic_string of some kind"
160
161     def __init__(self, val):
162         self.val = val
163
164     def to_string(self):
165         len = self.val['length']
166         return self.val['null_str'].string (gdb.target_charset(), length = len)
167
168     def display_hint (self):
169         return 'string'
170
171 pp_ls_encoding = None
172
173 class pp_ls (object):
174     "Print a std::basic_string of some kind"
175
176     def __init__(self, val):
177         self.val = val
178
179     def to_string(self):
180         length = self.val['len']
181         if pp_ls_encoding is not None:
182             if length >= 0:
183                 return self.val['lazy_str'].lazy_string(
184                         encoding = pp_ls_encoding,
185                         length = length)
186             else:
187                 return self.val['lazy_str'].lazy_string(
188                         encoding = pp_ls_encoding)
189         else:
190             if length >= 0:
191                 return self.val['lazy_str'].lazy_string(length = length)
192             else:
193                 return self.val['lazy_str'].lazy_string()
194
195     def display_hint (self):
196         return 'string'
197
198 class pp_hint_error (object):
199     "Throw error from display_hint"
200
201     def __init__(self, val):
202         self.val = val
203
204     def to_string(self):
205         return 'hint_error_val'
206
207     def display_hint (self):
208         raise Exception("hint failed")
209
210 class pp_children_as_list (object):
211     "Throw error from display_hint"
212
213     def __init__(self, val):
214         self.val = val
215
216     def to_string(self):
217         return 'children_as_list_val'
218
219     def children (self):
220         return [('one', 1)]
221
222 class pp_outer (object):
223     "Print struct outer"
224
225     def __init__ (self, val):
226         self.val = val
227
228     def to_string (self):
229         return "x = %s" % self.val['x']
230
231     def children (self):
232         yield 's', self.val['s']
233         yield 'x', self.val['x']
234
235 class MemoryErrorString (object):
236     "Raise an error"
237
238     def __init__(self, val):
239         self.val = val
240
241     def to_string(self):
242         raise gdb.MemoryError ("Cannot access memory.")
243
244     def display_hint (self):
245         return 'string'
246
247 class pp_eval_type (object):
248     def __init__(self, val):
249         self.val = val
250
251     def to_string(self):
252         gdb.execute("bt", to_string=True)
253         return "eval=<" + str(gdb.parse_and_eval("eval_func (123456789, 2, 3, 4, 5, 6, 7, 8)")) + ">"
254
255 class pp_int_typedef (object):
256     def __init__(self, val):
257         self.val = val
258
259     def to_string(self):
260         return "type=%s, val=%s" % (self.val.type, int(self.val))
261
262 class pp_int_typedef3 (object):
263     "A printer without a to_string method"
264
265     def __init__(self, val):
266         self.val = val
267
268     def children(self):
269         yield 's', 27
270
271 def lookup_function (val):
272     "Look-up and return a pretty-printer that can print val."
273
274     # Get the type.
275     type = val.type
276
277     # If it points to a reference, get the reference.
278     if type.code == gdb.TYPE_CODE_REF:
279         type = type.target ()
280
281     # Get the unqualified type, stripped of typedefs.
282     type = type.unqualified ().strip_typedefs ()
283
284     # Get the type name.    
285     typename = type.tag
286
287     if typename == None:
288         return None
289
290     # Iterate over local dictionary of types to determine
291     # if a printer is registered for that type.  Return an
292     # instantiation of the printer if found.
293     for function in pretty_printers_dict:
294         if function.match (typename):
295             return pretty_printers_dict[function] (val)
296         
297     # Cannot find a pretty printer.  Return None.
298
299     return None
300
301 def disable_lookup_function ():
302     lookup_function.enabled = False
303
304 def enable_lookup_function ():
305     lookup_function.enabled = True
306
307 # Lookup a printer for VAL in the typedefs dict.
308 def lookup_typedefs_function (val):
309     "Look-up and return a pretty-printer that can print val (typedefs)."
310
311     # Get the type.
312     type = val.type
313
314     if type == None or type.name == None or type.code != gdb.TYPE_CODE_TYPEDEF:
315         return None
316
317     # Iterate over local dictionary of typedef types to determine if a
318     # printer is registered for that type.  Return an instantiation of
319     # the printer if found.
320     for function in typedefs_pretty_printers_dict:
321         if function.match (type.name):
322             return typedefs_pretty_printers_dict[function] (val)
323
324     # Cannot find a pretty printer.
325     return None
326
327 def register_pretty_printers ():
328     pretty_printers_dict[re.compile ('^struct s$')]   = pp_s
329     pretty_printers_dict[re.compile ('^s$')]   = pp_s
330     pretty_printers_dict[re.compile ('^S$')]   = pp_s
331
332     pretty_printers_dict[re.compile ('^struct ss$')]  = pp_ss
333     pretty_printers_dict[re.compile ('^ss$')]  = pp_ss
334     pretty_printers_dict[re.compile ('^const S &$')]   = pp_s
335     pretty_printers_dict[re.compile ('^SSS$')]  = pp_sss
336     
337     pretty_printers_dict[re.compile ('^VirtualTest$')] =  pp_multiple_virtual
338     pretty_printers_dict[re.compile ('^Vbase1$')] =  pp_vbase1
339
340     pretty_printers_dict[re.compile ('^struct nullstr$')] = pp_nullstr
341     pretty_printers_dict[re.compile ('^nullstr$')] = pp_nullstr
342     
343     # Note that we purposely omit the typedef names here.
344     # Printer lookup is based on canonical name.
345     # However, we do need both tagged and untagged variants, to handle
346     # both the C and C++ cases.
347     pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print
348     pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter
349     pretty_printers_dict[re.compile ('^struct justchildren$')] = NoStringContainerPrinter
350     pretty_printers_dict[re.compile ('^string_repr$')] = string_print
351     pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
352     pretty_printers_dict[re.compile ('^justchildren$')] = NoStringContainerPrinter
353
354     pretty_printers_dict[re.compile ('^struct to_string_returns_value_inner$')] = ToStringReturnsValueInner
355     pretty_printers_dict[re.compile ('^to_string_returns_value_inner$')] = ToStringReturnsValueInner
356     pretty_printers_dict[re.compile ('^struct to_string_returns_value_wrapper$')] = ToStringReturnsValueWrapper
357     pretty_printers_dict[re.compile ('^to_string_returns_value_wrapper$')] = ToStringReturnsValueWrapper
358
359     pretty_printers_dict[re.compile ('^struct ns$')]  = pp_ns
360     pretty_printers_dict[re.compile ('^ns$')]  = pp_ns
361
362     pretty_printers_dict[re.compile ('^struct lazystring$')]  = pp_ls
363     pretty_printers_dict[re.compile ('^lazystring$')]  = pp_ls
364
365     pretty_printers_dict[re.compile ('^struct outerstruct$')]  = pp_outer
366     pretty_printers_dict[re.compile ('^outerstruct$')]  = pp_outer
367
368     pretty_printers_dict[re.compile ('^struct hint_error$')]  = pp_hint_error
369     pretty_printers_dict[re.compile ('^hint_error$')]  = pp_hint_error
370
371     pretty_printers_dict[re.compile ('^struct children_as_list$')]  = pp_children_as_list
372     pretty_printers_dict[re.compile ('^children_as_list$')]  = pp_children_as_list
373
374     pretty_printers_dict[re.compile ('^memory_error$')]  = MemoryErrorString
375
376     pretty_printers_dict[re.compile ('^eval_type_s$')] = pp_eval_type
377
378     typedefs_pretty_printers_dict[re.compile ('^int_type$')] = pp_int_typedef
379     typedefs_pretty_printers_dict[re.compile ('^int_type2$')] = pp_int_typedef
380     typedefs_pretty_printers_dict[re.compile ('^int_type3$')] = pp_int_typedef3
381
382 # Dict for struct types with typedefs fully stripped.
383 pretty_printers_dict = {}
384 # Dict for typedef types.
385 typedefs_pretty_printers_dict = {}
386
387 register_pretty_printers ()
388 gdb.pretty_printers.append (lookup_function)
389 gdb.pretty_printers.append (lookup_typedefs_function)
This page took 0.037486 seconds and 2 git commands to generate.