]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/lib/gdb/command/pretty_printers.py
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / python / lib / gdb / command / pretty_printers.py
CommitLineData
7b51bc51 1# Pretty-printer commands.
213516ef 2# Copyright (C) 2010-2023 Free Software Foundation, Inc.
7b51bc51
DE
3
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17"""GDB commands for working with pretty-printers."""
18
19import copy
20import gdb
21import re
22
23
24def parse_printer_regexps(arg):
25 """Internal utility to parse a pretty-printer command argv.
26
27 Arguments:
28 arg: The arguments to the command. The format is:
29 [object-regexp [name-regexp]].
30 Individual printers in a collection are named as
4e04c971 31 printer-name;subprinter-name.
7b51bc51
DE
32
33 Returns:
34 The result is a 3-tuple of compiled regular expressions, except that
35 the resulting compiled subprinter regexp is None if not provided.
36
37 Raises:
38 SyntaxError: an error processing ARG
39 """
40
13123da8 41 argv = gdb.string_to_argv(arg)
7b51bc51
DE
42 argc = len(argv)
43 object_regexp = "" # match everything
44 name_regexp = "" # match everything
45 subname_regexp = None
46 if argc > 3:
47 raise SyntaxError("too many arguments")
48 if argc >= 1:
49 object_regexp = argv[0]
50 if argc >= 2:
4e04c971 51 name_subname = argv[1].split(";", 1)
7b51bc51
DE
52 name_regexp = name_subname[0]
53 if len(name_subname) == 2:
54 subname_regexp = name_subname[1]
55 # That re.compile raises SyntaxError was determined empirically.
56 # We catch it and reraise it to provide a slightly more useful
57 # error message for the user.
58 try:
59 object_re = re.compile(object_regexp)
60 except SyntaxError:
61 raise SyntaxError("invalid object regexp: %s" % object_regexp)
62 try:
13123da8 63 name_re = re.compile(name_regexp)
7b51bc51
DE
64 except SyntaxError:
65 raise SyntaxError("invalid name regexp: %s" % name_regexp)
66 if subname_regexp is not None:
67 try:
68 subname_re = re.compile(subname_regexp)
69 except SyntaxError:
70 raise SyntaxError("invalid subname regexp: %s" % subname_regexp)
71 else:
72 subname_re = None
13123da8 73 return (object_re, name_re, subname_re)
7b51bc51
DE
74
75
76def printer_enabled_p(printer):
77 """Internal utility to see if printer (or subprinter) is enabled."""
78 if hasattr(printer, "enabled"):
79 return printer.enabled
80 else:
81 return True
82
83
84class InfoPrettyPrinter(gdb.Command):
85 """GDB command to list all registered pretty-printers.
86
13123da8 87 Usage: info pretty-printer [OBJECT-REGEXP [NAME-REGEXP]]
7b51bc51 88
13123da8
SM
89 OBJECT-REGEXP is a regular expression matching the objects to list.
90 Objects are "global", the program space's file, and the objfiles within
91 that program space.
7b51bc51 92
13123da8
SM
93 NAME-REGEXP matches the name of the pretty-printer.
94 Individual printers in a collection are named as
95 printer-name;subprinter-name."""
7b51bc51 96
13123da8
SM
97 def __init__(self):
98 super(InfoPrettyPrinter, self).__init__("info pretty-printer", gdb.COMMAND_DATA)
7b51bc51
DE
99
100 @staticmethod
101 def enabled_string(printer):
102 """Return "" if PRINTER is enabled, otherwise " [disabled]"."""
103 if printer_enabled_p(printer):
104 return ""
105 else:
106 return " [disabled]"
107
108 @staticmethod
109 def printer_name(printer):
110 """Return the printer's name."""
111 if hasattr(printer, "name"):
112 return printer.name
113 if hasattr(printer, "__name__"):
114 return printer.__name__
115 # This "shouldn't happen", but the public API allows for
116 # direct additions to the pretty-printer list, and we shouldn't
117 # crash because someone added a bogus printer.
118 # Plus we want to give the user a way to list unknown printers.
119 return "unknown"
120
121 def list_pretty_printers(self, pretty_printers, name_re, subname_re):
122 """Print a list of pretty-printers."""
123 # A potential enhancement is to provide an option to list printers in
124 # "lookup order" (i.e. unsorted).
13123da8
SM
125 sorted_pretty_printers = sorted(
126 copy.copy(pretty_printers), key=self.printer_name
127 )
7b51bc51
DE
128 for printer in sorted_pretty_printers:
129 name = self.printer_name(printer)
130 enabled = self.enabled_string(printer)
131 if name_re.match(name):
13123da8
SM
132 print(" %s%s" % (name, enabled))
133 if hasattr(printer, "subprinters") and printer.subprinters is not None:
134 sorted_subprinters = sorted(
135 copy.copy(printer.subprinters), key=self.printer_name
136 )
7b51bc51 137 for subprinter in sorted_subprinters:
13123da8
SM
138 if not subname_re or subname_re.match(subprinter.name):
139 print(
140 " %s%s"
141 % (subprinter.name, self.enabled_string(subprinter))
142 )
143
144 def invoke1(
145 self, title, printer_list, obj_name_to_match, object_re, name_re, subname_re
146 ):
75c8c9d7 147 """Subroutine of invoke to simplify it."""
7b51bc51 148 if printer_list and object_re.match(obj_name_to_match):
13123da8 149 print(title)
7b51bc51
DE
150 self.list_pretty_printers(printer_list, name_re, subname_re)
151
152 def invoke(self, arg, from_tty):
153 """GDB calls this to perform the command."""
154 (object_re, name_re, subname_re) = parse_printer_regexps(arg)
13123da8
SM
155 self.invoke1(
156 "global pretty-printers:",
157 gdb.pretty_printers,
158 "global",
159 object_re,
160 name_re,
161 subname_re,
162 )
7b51bc51 163 cp = gdb.current_progspace()
13123da8
SM
164 self.invoke1(
165 "progspace %s pretty-printers:" % cp.filename,
166 cp.pretty_printers,
167 "progspace",
168 object_re,
169 name_re,
170 subname_re,
171 )
7b51bc51 172 for objfile in gdb.objfiles():
13123da8
SM
173 self.invoke1(
174 "objfile %s pretty-printers:" % objfile.filename,
175 objfile.pretty_printers,
176 objfile.filename,
177 object_re,
178 name_re,
179 subname_re,
180 )
7b51bc51
DE
181
182
183def count_enabled_printers(pretty_printers):
184 """Return a 2-tuple of number of enabled and total printers."""
185 enabled = 0
186 total = 0
187 for printer in pretty_printers:
13123da8 188 if hasattr(printer, "subprinters") and printer.subprinters is not None:
7b51bc51
DE
189 if printer_enabled_p(printer):
190 for subprinter in printer.subprinters:
191 if printer_enabled_p(subprinter):
192 enabled += 1
193 total += len(printer.subprinters)
194 else:
195 if printer_enabled_p(printer):
196 enabled += 1
197 total += 1
198 return (enabled, total)
199
200
201def count_all_enabled_printers():
202 """Return a 2-tuble of the enabled state and total number of all printers.
203 This includes subprinters.
204 """
205 enabled_count = 0
206 total_count = 0
207 (t_enabled, t_total) = count_enabled_printers(gdb.pretty_printers)
208 enabled_count += t_enabled
209 total_count += t_total
13123da8
SM
210 (t_enabled, t_total) = count_enabled_printers(
211 gdb.current_progspace().pretty_printers
212 )
7b51bc51
DE
213 enabled_count += t_enabled
214 total_count += t_total
215 for objfile in gdb.objfiles():
216 (t_enabled, t_total) = count_enabled_printers(objfile.pretty_printers)
217 enabled_count += t_enabled
218 total_count += t_total
219 return (enabled_count, total_count)
220
221
222def pluralize(text, n, suffix="s"):
223 """Return TEXT pluralized if N != 1."""
224 if n != 1:
225 return "%s%s" % (text, suffix)
226 else:
227 return text
228
229
230def show_pretty_printer_enabled_summary():
231 """Print the number of printers enabled/disabled.
232 We count subprinters individually.
233 """
234 (enabled_count, total_count) = count_all_enabled_printers()
13123da8 235 print("%d of %d printers enabled" % (enabled_count, total_count))
7b51bc51
DE
236
237
13123da8 238def do_enable_pretty_printer_1(pretty_printers, name_re, subname_re, flag):
7b51bc51
DE
239 """Worker for enabling/disabling pretty-printers.
240
241 Arguments:
242 pretty_printers: list of pretty-printers
243 name_re: regular-expression object to select printers
244 subname_re: regular expression object to select subprinters or None
245 if all are affected
246 flag: True for Enable, False for Disable
247
248 Returns:
249 The number of printers affected.
250 This is just for informational purposes for the user.
251 """
252 total = 0
253 for printer in pretty_printers:
13123da8
SM
254 if (
255 hasattr(printer, "name")
256 and name_re.match(printer.name)
257 or hasattr(printer, "__name__")
258 and name_re.match(printer.__name__)
259 ):
260 if hasattr(printer, "subprinters") and printer.subprinters is not None:
7b51bc51
DE
261 if not subname_re:
262 # Only record printers that change state.
263 if printer_enabled_p(printer) != flag:
264 for subprinter in printer.subprinters:
265 if printer_enabled_p(subprinter):
266 total += 1
267 # NOTE: We preserve individual subprinter settings.
268 printer.enabled = flag
269 else:
270 # NOTE: Whether this actually disables the subprinter
271 # depends on whether the printer's lookup function supports
272 # the "enable" API. We can only assume it does.
273 for subprinter in printer.subprinters:
274 if subname_re.match(subprinter.name):
275 # Only record printers that change state.
13123da8
SM
276 if (
277 printer_enabled_p(printer)
278 and printer_enabled_p(subprinter) != flag
279 ):
280 total += 1
281 subprinter.enabled = flag
7b51bc51
DE
282 else:
283 # This printer has no subprinters.
284 # If the user does "disable pretty-printer .* .* foo"
285 # should we disable printers that don't have subprinters?
286 # How do we apply "foo" in this context? Since there is no
287 # "foo" subprinter it feels like we should skip this printer.
288 # There's still the issue of how to handle
289 # "disable pretty-printer .* .* .*", and every other variation
290 # that can match everything. For now punt and only support
291 # "disable pretty-printer .* .*" (i.e. subname is elided)
292 # to disable everything.
293 if not subname_re:
294 # Only record printers that change state.
295 if printer_enabled_p(printer) != flag:
296 total += 1
297 printer.enabled = flag
298 return total
299
300
13123da8 301def do_enable_pretty_printer(arg, flag):
7b51bc51
DE
302 """Internal worker for enabling/disabling pretty-printers."""
303 (object_re, name_re, subname_re) = parse_printer_regexps(arg)
304
305 total = 0
306 if object_re.match("global"):
13123da8
SM
307 total += do_enable_pretty_printer_1(
308 gdb.pretty_printers, name_re, subname_re, flag
309 )
7b51bc51
DE
310 cp = gdb.current_progspace()
311 if object_re.match("progspace"):
13123da8
SM
312 total += do_enable_pretty_printer_1(
313 cp.pretty_printers, name_re, subname_re, flag
314 )
7b51bc51
DE
315 for objfile in gdb.objfiles():
316 if object_re.match(objfile.filename):
13123da8
SM
317 total += do_enable_pretty_printer_1(
318 objfile.pretty_printers, name_re, subname_re, flag
319 )
7b51bc51
DE
320
321 if flag:
322 state = "enabled"
323 else:
324 state = "disabled"
13123da8 325 print("%d %s %s" % (total, pluralize("printer", total), state))
7b51bc51
DE
326
327 # Print the total list of printers currently enabled/disabled.
328 # This is to further assist the user in determining whether the result
329 # is expected. Since we use regexps to select it's useful.
330 show_pretty_printer_enabled_summary()
331
332
333# Enable/Disable one or more pretty-printers.
334#
335# This is intended for use when a broken pretty-printer is shipped/installed
336# and the user wants to disable that printer without disabling all the other
337# printers.
338#
339# A useful addition would be -v (verbose) to show each printer affected.
340
13123da8
SM
341
342class EnablePrettyPrinter(gdb.Command):
7b51bc51
DE
343 """GDB command to enable the specified pretty-printer.
344
13123da8 345 Usage: enable pretty-printer [OBJECT-REGEXP [NAME-REGEXP]]
7b51bc51 346
13123da8
SM
347 OBJECT-REGEXP is a regular expression matching the objects to examine.
348 Objects are "global", the program space's file, and the objfiles within
349 that program space.
7b51bc51 350
13123da8
SM
351 NAME-REGEXP matches the name of the pretty-printer.
352 Individual printers in a collection are named as
353 printer-name;subprinter-name."""
7b51bc51
DE
354
355 def __init__(self):
13123da8
SM
356 super(EnablePrettyPrinter, self).__init__(
357 "enable pretty-printer", gdb.COMMAND_DATA
358 )
7b51bc51
DE
359
360 def invoke(self, arg, from_tty):
361 """GDB calls this to perform the command."""
362 do_enable_pretty_printer(arg, True)
363
364
13123da8 365class DisablePrettyPrinter(gdb.Command):
7b51bc51
DE
366 """GDB command to disable the specified pretty-printer.
367
13123da8 368 Usage: disable pretty-printer [OBJECT-REGEXP [NAME-REGEXP]]
7b51bc51 369
13123da8
SM
370 OBJECT-REGEXP is a regular expression matching the objects to examine.
371 Objects are "global", the program space's file, and the objfiles within
372 that program space.
7b51bc51 373
13123da8
SM
374 NAME-REGEXP matches the name of the pretty-printer.
375 Individual printers in a collection are named as
376 printer-name;subprinter-name."""
7b51bc51
DE
377
378 def __init__(self):
13123da8
SM
379 super(DisablePrettyPrinter, self).__init__(
380 "disable pretty-printer", gdb.COMMAND_DATA
381 )
7b51bc51
DE
382
383 def invoke(self, arg, from_tty):
384 """GDB calls this to perform the command."""
385 do_enable_pretty_printer(arg, False)
386
387
388def register_pretty_printer_commands():
389 """Call from a top level script to install the pretty-printer commands."""
390 InfoPrettyPrinter()
391 EnablePrettyPrinter()
392 DisablePrettyPrinter()
5e239b84 393
13123da8 394
5e239b84 395register_pretty_printer_commands()