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