]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/lib/gdb/command/pretty_printers.py
Update copyright year range in all GDB files.
[thirdparty/binutils-gdb.git] / gdb / python / lib / gdb / command / pretty_printers.py
CommitLineData
7b51bc51 1# Pretty-printer commands.
42a4f53d 2# Copyright (C) 2010-2019 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
41 argv = gdb.string_to_argv(arg);
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:
63 name_re = re.compile (name_regexp)
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
73 return(object_re, name_re, subname_re)
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
2fb009bb 87Usage: info pretty-printer [OBJECT-REGEXP [NAME-REGEXP]]
7b51bc51 88
2fb009bb
TT
89OBJECT-REGEXP is a regular expression matching the objects to list.
90Objects are "global", the program space's file, and the objfiles within
91that program space.
7b51bc51 92
2fb009bb
TT
93NAME-REGEXP matches the name of the pretty-printer.
94Individual printers in a collection are named as
95printer-name;subprinter-name."""
7b51bc51
DE
96
97 def __init__ (self):
98 super(InfoPrettyPrinter, self).__init__("info pretty-printer",
99 gdb.COMMAND_DATA)
100
101 @staticmethod
102 def enabled_string(printer):
103 """Return "" if PRINTER is enabled, otherwise " [disabled]"."""
104 if printer_enabled_p(printer):
105 return ""
106 else:
107 return " [disabled]"
108
109 @staticmethod
110 def printer_name(printer):
111 """Return the printer's name."""
112 if hasattr(printer, "name"):
113 return 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.
120 return "unknown"
121
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).
9a27f2c6
PK
126 sorted_pretty_printers = sorted (copy.copy(pretty_printers),
127 key = self.printer_name)
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):
9a27f2c6 132 print (" %s%s" % (name, enabled))
7b51bc51
DE
133 if (hasattr(printer, "subprinters") and
134 printer.subprinters is not None):
9a27f2c6
PK
135 sorted_subprinters = sorted (copy.copy(printer.subprinters),
136 key = self.printer_name)
7b51bc51
DE
137 for subprinter in sorted_subprinters:
138 if (not subname_re or
139 subname_re.match(subprinter.name)):
140 print (" %s%s" %
141 (subprinter.name,
142 self.enabled_string(subprinter)))
143
144 def invoke1(self, title, printer_list,
145 obj_name_to_match, object_re, name_re, subname_re):
75c8c9d7 146 """Subroutine of invoke to simplify it."""
7b51bc51 147 if printer_list and object_re.match(obj_name_to_match):
9a27f2c6 148 print (title)
7b51bc51
DE
149 self.list_pretty_printers(printer_list, name_re, subname_re)
150
151 def invoke(self, arg, from_tty):
152 """GDB calls this to perform the command."""
153 (object_re, name_re, subname_re) = parse_printer_regexps(arg)
154 self.invoke1("global pretty-printers:", gdb.pretty_printers,
155 "global", object_re, name_re, subname_re)
156 cp = gdb.current_progspace()
157 self.invoke1("progspace %s pretty-printers:" % cp.filename,
158 cp.pretty_printers, "progspace",
159 object_re, name_re, subname_re)
160 for objfile in gdb.objfiles():
3c6618cd 161 self.invoke1("objfile %s pretty-printers:" % objfile.filename,
7b51bc51
DE
162 objfile.pretty_printers, objfile.filename,
163 object_re, name_re, subname_re)
164
165
166def count_enabled_printers(pretty_printers):
167 """Return a 2-tuple of number of enabled and total printers."""
168 enabled = 0
169 total = 0
170 for printer in pretty_printers:
171 if (hasattr(printer, "subprinters")
172 and printer.subprinters is not None):
173 if printer_enabled_p(printer):
174 for subprinter in printer.subprinters:
175 if printer_enabled_p(subprinter):
176 enabled += 1
177 total += len(printer.subprinters)
178 else:
179 if printer_enabled_p(printer):
180 enabled += 1
181 total += 1
182 return (enabled, total)
183
184
185def count_all_enabled_printers():
186 """Return a 2-tuble of the enabled state and total number of all printers.
187 This includes subprinters.
188 """
189 enabled_count = 0
190 total_count = 0
191 (t_enabled, t_total) = count_enabled_printers(gdb.pretty_printers)
192 enabled_count += t_enabled
193 total_count += t_total
194 (t_enabled, t_total) = count_enabled_printers(gdb.current_progspace().pretty_printers)
195 enabled_count += t_enabled
196 total_count += t_total
197 for objfile in gdb.objfiles():
198 (t_enabled, t_total) = count_enabled_printers(objfile.pretty_printers)
199 enabled_count += t_enabled
200 total_count += t_total
201 return (enabled_count, total_count)
202
203
204def pluralize(text, n, suffix="s"):
205 """Return TEXT pluralized if N != 1."""
206 if n != 1:
207 return "%s%s" % (text, suffix)
208 else:
209 return text
210
211
212def show_pretty_printer_enabled_summary():
213 """Print the number of printers enabled/disabled.
214 We count subprinters individually.
215 """
216 (enabled_count, total_count) = count_all_enabled_printers()
9a27f2c6 217 print ("%d of %d printers enabled" % (enabled_count, total_count))
7b51bc51
DE
218
219
220def do_enable_pretty_printer_1 (pretty_printers, name_re, subname_re, flag):
221 """Worker for enabling/disabling pretty-printers.
222
223 Arguments:
224 pretty_printers: list of pretty-printers
225 name_re: regular-expression object to select printers
226 subname_re: regular expression object to select subprinters or None
227 if all are affected
228 flag: True for Enable, False for Disable
229
230 Returns:
231 The number of printers affected.
232 This is just for informational purposes for the user.
233 """
234 total = 0
235 for printer in pretty_printers:
236 if (hasattr(printer, "name") and name_re.match(printer.name) or
237 hasattr(printer, "__name__") and name_re.match(printer.__name__)):
f61a2da7
DE
238 if (hasattr(printer, "subprinters") and
239 printer.subprinters is not None):
7b51bc51
DE
240 if not subname_re:
241 # Only record printers that change state.
242 if printer_enabled_p(printer) != flag:
243 for subprinter in printer.subprinters:
244 if printer_enabled_p(subprinter):
245 total += 1
246 # NOTE: We preserve individual subprinter settings.
247 printer.enabled = flag
248 else:
249 # NOTE: Whether this actually disables the subprinter
250 # depends on whether the printer's lookup function supports
251 # the "enable" API. We can only assume it does.
252 for subprinter in printer.subprinters:
253 if subname_re.match(subprinter.name):
254 # Only record printers that change state.
255 if (printer_enabled_p(printer) and
256 printer_enabled_p(subprinter) != flag):
257 total += 1
258 subprinter.enabled = flag
259 else:
260 # This printer has no subprinters.
261 # If the user does "disable pretty-printer .* .* foo"
262 # should we disable printers that don't have subprinters?
263 # How do we apply "foo" in this context? Since there is no
264 # "foo" subprinter it feels like we should skip this printer.
265 # There's still the issue of how to handle
266 # "disable pretty-printer .* .* .*", and every other variation
267 # that can match everything. For now punt and only support
268 # "disable pretty-printer .* .*" (i.e. subname is elided)
269 # to disable everything.
270 if not subname_re:
271 # Only record printers that change state.
272 if printer_enabled_p(printer) != flag:
273 total += 1
274 printer.enabled = flag
275 return total
276
277
278def do_enable_pretty_printer (arg, flag):
279 """Internal worker for enabling/disabling pretty-printers."""
280 (object_re, name_re, subname_re) = parse_printer_regexps(arg)
281
282 total = 0
283 if object_re.match("global"):
284 total += do_enable_pretty_printer_1(gdb.pretty_printers,
285 name_re, subname_re, flag)
286 cp = gdb.current_progspace()
287 if object_re.match("progspace"):
288 total += do_enable_pretty_printer_1(cp.pretty_printers,
289 name_re, subname_re, flag)
290 for objfile in gdb.objfiles():
291 if object_re.match(objfile.filename):
292 total += do_enable_pretty_printer_1(objfile.pretty_printers,
293 name_re, subname_re, flag)
294
295 if flag:
296 state = "enabled"
297 else:
298 state = "disabled"
9a27f2c6 299 print ("%d %s %s" % (total, pluralize("printer", total), state))
7b51bc51
DE
300
301 # Print the total list of printers currently enabled/disabled.
302 # This is to further assist the user in determining whether the result
303 # is expected. Since we use regexps to select it's useful.
304 show_pretty_printer_enabled_summary()
305
306
307# Enable/Disable one or more pretty-printers.
308#
309# This is intended for use when a broken pretty-printer is shipped/installed
310# and the user wants to disable that printer without disabling all the other
311# printers.
312#
313# A useful addition would be -v (verbose) to show each printer affected.
314
315class EnablePrettyPrinter (gdb.Command):
316 """GDB command to enable the specified pretty-printer.
317
2fb009bb 318Usage: enable pretty-printer [OBJECT-REGEXP [NAME-REGEXP]]
7b51bc51 319
2fb009bb
TT
320OBJECT-REGEXP is a regular expression matching the objects to examine.
321Objects are "global", the program space's file, and the objfiles within
322that program space.
7b51bc51 323
2fb009bb
TT
324NAME-REGEXP matches the name of the pretty-printer.
325Individual printers in a collection are named as
326printer-name;subprinter-name."""
7b51bc51
DE
327
328 def __init__(self):
329 super(EnablePrettyPrinter, self).__init__("enable pretty-printer",
330 gdb.COMMAND_DATA)
331
332 def invoke(self, arg, from_tty):
333 """GDB calls this to perform the command."""
334 do_enable_pretty_printer(arg, True)
335
336
337class DisablePrettyPrinter (gdb.Command):
338 """GDB command to disable the specified pretty-printer.
339
2fb009bb 340Usage: disable pretty-printer [OBJECT-REGEXP [NAME-REGEXP]]
7b51bc51 341
2fb009bb
TT
342OBJECT-REGEXP is a regular expression matching the objects to examine.
343Objects are "global", the program space's file, and the objfiles within
344that program space.
7b51bc51 345
2fb009bb
TT
346NAME-REGEXP matches the name of the pretty-printer.
347Individual printers in a collection are named as
348printer-name;subprinter-name."""
7b51bc51
DE
349
350 def __init__(self):
351 super(DisablePrettyPrinter, self).__init__("disable pretty-printer",
352 gdb.COMMAND_DATA)
353
354 def invoke(self, arg, from_tty):
355 """GDB calls this to perform the command."""
356 do_enable_pretty_printer(arg, False)
357
358
359def register_pretty_printer_commands():
360 """Call from a top level script to install the pretty-printer commands."""
361 InfoPrettyPrinter()
362 EnablePrettyPrinter()
363 DisablePrettyPrinter()
5e239b84
PM
364
365register_pretty_printer_commands()