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