]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/lib/gdb/command/pretty_printers.py
f62d329c54df022c2f1bb6139d1b0093878edd38
1 # Pretty-printer commands.
2 # Copyright (C) 2010-2025 Free Software Foundation, Inc.
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.
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.
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/>.
17 """GDB commands for working with pretty-printers."""
25 def parse_printer_regexps(arg
):
26 """Internal utility to parse a pretty-printer command argv.
29 arg: The arguments to the command. The format is:
30 [object-regexp [name-regexp]].
31 Individual printers in a collection are named as
32 printer-name;subprinter-name.
35 The result is a 3-tuple of compiled regular expressions, except that
36 the resulting compiled subprinter regexp is None if not provided.
39 SyntaxError: an error processing ARG
42 argv
= gdb
.string_to_argv(arg
)
44 object_regexp
= "" # match everything
45 name_regexp
= "" # match everything
48 raise SyntaxError("too many arguments")
50 object_regexp
= argv
[0]
52 name_subname
= argv
[1].split(";", 1)
53 name_regexp
= name_subname
[0]
54 if len(name_subname
) == 2:
55 subname_regexp
= name_subname
[1]
56 # That re.compile raises SyntaxError was determined empirically.
57 # We catch it and reraise it to provide a slightly more useful
58 # error message for the user.
60 object_re
= re
.compile(object_regexp
)
62 raise SyntaxError("invalid object regexp: %s" % object_regexp
)
64 name_re
= re
.compile(name_regexp
)
66 raise SyntaxError("invalid name regexp: %s" % name_regexp
)
67 if subname_regexp
is not None:
69 subname_re
= re
.compile(subname_regexp
)
71 raise SyntaxError("invalid subname regexp: %s" % subname_regexp
)
74 return (object_re
, name_re
, subname_re
)
77 def printer_enabled_p(printer
):
78 """Internal utility to see if printer (or subprinter) is enabled."""
79 if hasattr(printer
, "enabled"):
80 return printer
.enabled
85 class InfoPrettyPrinter(gdb
.Command
):
86 """GDB command to list all registered pretty-printers.
88 Usage: info pretty-printer [OBJECT-REGEXP [NAME-REGEXP]]
90 OBJECT-REGEXP is a regular expression matching the objects to list.
91 Objects are "global", the program space's file, and the objfiles within
94 NAME-REGEXP matches the name of the pretty-printer.
95 Individual printers in a collection are named as
96 printer-name;subprinter-name."""
99 super(InfoPrettyPrinter
, self
).__init
__("info pretty-printer", gdb
.COMMAND_DATA
)
102 def enabled_string(printer
):
103 """Return "" if PRINTER is enabled, otherwise " [disabled]"."""
104 if printer_enabled_p(printer
):
110 def printer_name(printer
):
111 """Return the printer's name."""
112 if hasattr(printer
, "name"):
114 if hasattr(printer
, "__name__"):
115 return printer
.__name
__
116 # This "shouldn't happen", but the public API allows for
117 # direct additions to the pretty-printer list, and we shouldn't
118 # crash because someone added a bogus printer.
119 # Plus we want to give the user a way to list unknown printers.
122 def list_pretty_printers(self
, pretty_printers
, name_re
, subname_re
):
123 """Print a list of pretty-printers."""
124 # A potential enhancement is to provide an option to list printers in
125 # "lookup order" (i.e. unsorted).
126 sorted_pretty_printers
= sorted(
127 copy
.copy(pretty_printers
), key
=self
.printer_name
129 for printer
in sorted_pretty_printers
:
130 name
= self
.printer_name(printer
)
131 enabled
= self
.enabled_string(printer
)
132 if name_re
.match(name
):
133 print(" %s%s" % (name
, enabled
))
134 if hasattr(printer
, "subprinters") and printer
.subprinters
is not None:
135 sorted_subprinters
= sorted(
136 copy
.copy(printer
.subprinters
), key
=self
.printer_name
138 for subprinter
in sorted_subprinters
:
139 if not subname_re
or subname_re
.match(subprinter
.name
):
142 % (subprinter
.name
, self
.enabled_string(subprinter
))
146 self
, title
, printer_list
, obj_name_to_match
, object_re
, name_re
, subname_re
148 """Subroutine of invoke to simplify it."""
149 if printer_list
and object_re
.match(obj_name_to_match
):
151 self
.list_pretty_printers(printer_list
, name_re
, subname_re
)
153 def invoke(self
, arg
, from_tty
):
154 """GDB calls this to perform the command."""
155 (object_re
, name_re
, subname_re
) = parse_printer_regexps(arg
)
157 "global pretty-printers:",
164 cp
= gdb
.current_progspace()
166 "progspace %s pretty-printers:" % cp
.filename
,
173 for objfile
in gdb
.objfiles():
175 "objfile %s pretty-printers:" % objfile
.filename
,
176 objfile
.pretty_printers
,
184 def count_enabled_printers(pretty_printers
):
185 """Return a 2-tuple of number of enabled and total printers."""
188 for printer
in pretty_printers
:
189 if hasattr(printer
, "subprinters") and printer
.subprinters
is not None:
190 if printer_enabled_p(printer
):
191 for subprinter
in printer
.subprinters
:
192 if printer_enabled_p(subprinter
):
194 total
+= len(printer
.subprinters
)
196 if printer_enabled_p(printer
):
199 return (enabled
, total
)
202 def count_all_enabled_printers():
203 """Return a 2-tuble of the enabled state and total number of all printers.
204 This includes subprinters.
208 (t_enabled
, t_total
) = count_enabled_printers(gdb
.pretty_printers
)
209 enabled_count
+= t_enabled
210 total_count
+= t_total
211 (t_enabled
, t_total
) = count_enabled_printers(
212 gdb
.current_progspace().pretty_printers
214 enabled_count
+= t_enabled
215 total_count
+= t_total
216 for objfile
in gdb
.objfiles():
217 (t_enabled
, t_total
) = count_enabled_printers(objfile
.pretty_printers
)
218 enabled_count
+= t_enabled
219 total_count
+= t_total
220 return (enabled_count
, total_count
)
223 def pluralize(text
, n
, suffix
="s"):
224 """Return TEXT pluralized if N != 1."""
226 return "%s%s" % (text
, suffix
)
231 def show_pretty_printer_enabled_summary():
232 """Print the number of printers enabled/disabled.
233 We count subprinters individually.
235 (enabled_count
, total_count
) = count_all_enabled_printers()
236 print("%d of %d printers enabled" % (enabled_count
, total_count
))
239 def do_enable_pretty_printer_1(pretty_printers
, name_re
, subname_re
, flag
):
240 """Worker for enabling/disabling pretty-printers.
243 pretty_printers: list of pretty-printers
244 name_re: regular-expression object to select printers
245 subname_re: regular expression object to select subprinters or None
247 flag: True for Enable, False for Disable
250 The number of printers affected.
251 This is just for informational purposes for the user.
254 for printer
in pretty_printers
:
256 hasattr(printer
, "name")
257 and name_re
.match(printer
.name
)
258 or hasattr(printer
, "__name__")
259 and name_re
.match(printer
.__name
__)
261 if hasattr(printer
, "subprinters") and printer
.subprinters
is not None:
263 # Only record printers that change state.
264 if printer_enabled_p(printer
) != flag
:
265 for subprinter
in printer
.subprinters
:
266 if printer_enabled_p(subprinter
):
268 # NOTE: We preserve individual subprinter settings.
269 printer
.enabled
= flag
271 # NOTE: Whether this actually disables the subprinter
272 # depends on whether the printer's lookup function supports
273 # the "enable" API. We can only assume it does.
274 for subprinter
in printer
.subprinters
:
275 if subname_re
.match(subprinter
.name
):
276 # Only record printers that change state.
278 printer_enabled_p(printer
)
279 and printer_enabled_p(subprinter
) != flag
282 subprinter
.enabled
= flag
284 # This printer has no subprinters.
285 # If the user does "disable pretty-printer .* .* foo"
286 # should we disable printers that don't have subprinters?
287 # How do we apply "foo" in this context? Since there is no
288 # "foo" subprinter it feels like we should skip this printer.
289 # There's still the issue of how to handle
290 # "disable pretty-printer .* .* .*", and every other variation
291 # that can match everything. For now punt and only support
292 # "disable pretty-printer .* .*" (i.e. subname is elided)
293 # to disable everything.
295 # Only record printers that change state.
296 if printer_enabled_p(printer
) != flag
:
298 printer
.enabled
= flag
302 def do_enable_pretty_printer(arg
, flag
):
303 """Internal worker for enabling/disabling pretty-printers."""
304 (object_re
, name_re
, subname_re
) = parse_printer_regexps(arg
)
307 if object_re
.match("global"):
308 total
+= do_enable_pretty_printer_1(
309 gdb
.pretty_printers
, name_re
, subname_re
, flag
311 cp
= gdb
.current_progspace()
312 if object_re
.match("progspace"):
313 total
+= do_enable_pretty_printer_1(
314 cp
.pretty_printers
, name_re
, subname_re
, flag
316 for objfile
in gdb
.objfiles():
317 if object_re
.match(objfile
.filename
):
318 total
+= do_enable_pretty_printer_1(
319 objfile
.pretty_printers
, name_re
, subname_re
, flag
326 print("%d %s %s" % (total
, pluralize("printer", total
), state
))
328 # Print the total list of printers currently enabled/disabled.
329 # This is to further assist the user in determining whether the result
330 # is expected. Since we use regexps to select it's useful.
331 show_pretty_printer_enabled_summary()
334 # Enable/Disable one or more pretty-printers.
336 # This is intended for use when a broken pretty-printer is shipped/installed
337 # and the user wants to disable that printer without disabling all the other
340 # A useful addition would be -v (verbose) to show each printer affected.
343 class EnablePrettyPrinter(gdb
.Command
):
344 """GDB command to enable the specified pretty-printer.
346 Usage: enable pretty-printer [OBJECT-REGEXP [NAME-REGEXP]]
348 OBJECT-REGEXP is a regular expression matching the objects to examine.
349 Objects are "global", the program space's file, and the objfiles within
352 NAME-REGEXP matches the name of the pretty-printer.
353 Individual printers in a collection are named as
354 printer-name;subprinter-name."""
357 super(EnablePrettyPrinter
, self
).__init
__(
358 "enable pretty-printer", gdb
.COMMAND_DATA
361 def invoke(self
, arg
, from_tty
):
362 """GDB calls this to perform the command."""
363 do_enable_pretty_printer(arg
, True)
366 class DisablePrettyPrinter(gdb
.Command
):
367 """GDB command to disable the specified pretty-printer.
369 Usage: disable pretty-printer [OBJECT-REGEXP [NAME-REGEXP]]
371 OBJECT-REGEXP is a regular expression matching the objects to examine.
372 Objects are "global", the program space's file, and the objfiles within
375 NAME-REGEXP matches the name of the pretty-printer.
376 Individual printers in a collection are named as
377 printer-name;subprinter-name."""
380 super(DisablePrettyPrinter
, self
).__init
__(
381 "disable pretty-printer", gdb
.COMMAND_DATA
384 def invoke(self
, arg
, from_tty
):
385 """GDB calls this to perform the command."""
386 do_enable_pretty_printer(arg
, False)
389 def register_pretty_printer_commands():
390 """Call from a top level script to install the pretty-printer commands."""
392 EnablePrettyPrinter()
393 DisablePrettyPrinter()
396 register_pretty_printer_commands()