GDB (API)
/home/stan/gdb/src/gdb/python/lib/gdb/command/pretty_printers.py
Go to the documentation of this file.
00001 # Pretty-printer commands.
00002 # Copyright (C) 2010-2013 Free Software Foundation, Inc.
00003 
00004 # This program is free software; you can redistribute it and/or modify
00005 # it under the terms of the GNU General Public License as published by
00006 # the Free Software Foundation; either version 3 of the License, or
00007 # (at your option) any later version.
00008 #
00009 # This program is distributed in the hope that it will be useful,
00010 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 # GNU General Public License for more details.
00013 #
00014 # You should have received a copy of the GNU General Public License
00015 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 """GDB commands for working with pretty-printers."""
00018 
00019 import copy
00020 import gdb
00021 import re
00022 
00023 
00024 def parse_printer_regexps(arg):
00025     """Internal utility to parse a pretty-printer command argv.
00026 
00027     Arguments:
00028         arg: The arguments to the command.  The format is:
00029              [object-regexp [name-regexp]].
00030              Individual printers in a collection are named as
00031              printer-name;subprinter-name.
00032 
00033     Returns:
00034         The result is a 3-tuple of compiled regular expressions, except that
00035         the resulting compiled subprinter regexp is None if not provided.
00036 
00037     Raises:
00038         SyntaxError: an error processing ARG
00039     """
00040 
00041     argv = gdb.string_to_argv(arg);
00042     argc = len(argv)
00043     object_regexp = ""  # match everything
00044     name_regexp = ""  # match everything
00045     subname_regexp = None
00046     if argc > 3:
00047         raise SyntaxError("too many arguments")
00048     if argc >= 1:
00049         object_regexp = argv[0]
00050     if argc >= 2:
00051         name_subname = argv[1].split(";", 1)
00052         name_regexp = name_subname[0]
00053         if len(name_subname) == 2:
00054             subname_regexp = name_subname[1]
00055     # That re.compile raises SyntaxError was determined empirically.
00056     # We catch it and reraise it to provide a slightly more useful
00057     # error message for the user.
00058     try:
00059         object_re = re.compile(object_regexp)
00060     except SyntaxError:
00061         raise SyntaxError("invalid object regexp: %s" % object_regexp)
00062     try:
00063         name_re = re.compile (name_regexp)
00064     except SyntaxError:
00065         raise SyntaxError("invalid name regexp: %s" % name_regexp)
00066     if subname_regexp is not None:
00067         try:
00068             subname_re = re.compile(subname_regexp)
00069         except SyntaxError:
00070             raise SyntaxError("invalid subname regexp: %s" % subname_regexp)
00071     else:
00072         subname_re = None
00073     return(object_re, name_re, subname_re)
00074 
00075 
00076 def printer_enabled_p(printer):
00077     """Internal utility to see if printer (or subprinter) is enabled."""
00078     if hasattr(printer, "enabled"):
00079         return printer.enabled
00080     else:
00081         return True
00082 
00083 
00084 class InfoPrettyPrinter(gdb.Command):
00085     """GDB command to list all registered pretty-printers.
00086 
00087     Usage: info pretty-printer [object-regexp [name-regexp]]
00088 
00089     OBJECT-REGEXP is a regular expression matching the objects to list.
00090     Objects are "global", the program space's file, and the objfiles within
00091     that program space.
00092 
00093     NAME-REGEXP matches the name of the pretty-printer.
00094     Individual printers in a collection are named as
00095     printer-name;subprinter-name.
00096     """
00097 
00098     def __init__ (self):
00099         super(InfoPrettyPrinter, self).__init__("info pretty-printer",
00100                                                  gdb.COMMAND_DATA)
00101 
00102     @staticmethod
00103     def enabled_string(printer):
00104         """Return "" if PRINTER is enabled, otherwise " [disabled]"."""
00105         if printer_enabled_p(printer):
00106             return ""
00107         else:
00108             return " [disabled]"
00109 
00110     @staticmethod
00111     def printer_name(printer):
00112         """Return the printer's name."""
00113         if hasattr(printer, "name"):
00114             return printer.name
00115         if hasattr(printer, "__name__"):
00116             return printer.__name__
00117         # This "shouldn't happen", but the public API allows for
00118         # direct additions to the pretty-printer list, and we shouldn't
00119         # crash because someone added a bogus printer.
00120         # Plus we want to give the user a way to list unknown printers.
00121         return "unknown"
00122 
00123     def list_pretty_printers(self, pretty_printers, name_re, subname_re):
00124         """Print a list of pretty-printers."""
00125         # A potential enhancement is to provide an option to list printers in
00126         # "lookup order" (i.e. unsorted).
00127         sorted_pretty_printers = sorted (copy.copy(pretty_printers),
00128                                          key = self.printer_name)
00129         for printer in sorted_pretty_printers:
00130             name = self.printer_name(printer)
00131             enabled = self.enabled_string(printer)
00132             if name_re.match(name):
00133                 print ("  %s%s" % (name, enabled))
00134                 if (hasattr(printer, "subprinters") and
00135                     printer.subprinters is not None):
00136                     sorted_subprinters = sorted (copy.copy(printer.subprinters),
00137                                                  key = self.printer_name)
00138                     for subprinter in sorted_subprinters:
00139                         if (not subname_re or
00140                             subname_re.match(subprinter.name)):
00141                             print ("    %s%s" %
00142                                    (subprinter.name,
00143                                     self.enabled_string(subprinter)))
00144 
00145     def invoke1(self, title, printer_list,
00146                 obj_name_to_match, object_re, name_re, subname_re):
00147         """Subroutine of invoke to simplify it."""
00148         if printer_list and object_re.match(obj_name_to_match):
00149             print (title)
00150             self.list_pretty_printers(printer_list, name_re, subname_re)
00151 
00152     def invoke(self, arg, from_tty):
00153         """GDB calls this to perform the command."""
00154         (object_re, name_re, subname_re) = parse_printer_regexps(arg)
00155         self.invoke1("global pretty-printers:", gdb.pretty_printers,
00156                      "global", object_re, name_re, subname_re)
00157         cp = gdb.current_progspace()
00158         self.invoke1("progspace %s pretty-printers:" % cp.filename,
00159                      cp.pretty_printers, "progspace",
00160                      object_re, name_re, subname_re)
00161         for objfile in gdb.objfiles():
00162             self.invoke1("  objfile %s pretty-printers:" % objfile.filename,
00163                          objfile.pretty_printers, objfile.filename,
00164                          object_re, name_re, subname_re)
00165 
00166 
00167 def count_enabled_printers(pretty_printers):
00168     """Return a 2-tuple of number of enabled and total printers."""
00169     enabled = 0
00170     total = 0
00171     for printer in pretty_printers:
00172         if (hasattr(printer, "subprinters")
00173             and printer.subprinters is not None):
00174             if printer_enabled_p(printer):
00175                 for subprinter in printer.subprinters:
00176                     if printer_enabled_p(subprinter):
00177                         enabled += 1
00178             total += len(printer.subprinters)
00179         else:
00180             if printer_enabled_p(printer):
00181                 enabled += 1
00182             total += 1
00183     return (enabled, total)
00184 
00185 
00186 def count_all_enabled_printers():
00187     """Return a 2-tuble of the enabled state and total number of all printers.
00188     This includes subprinters.
00189     """
00190     enabled_count = 0
00191     total_count = 0
00192     (t_enabled, t_total) = count_enabled_printers(gdb.pretty_printers)
00193     enabled_count += t_enabled
00194     total_count += t_total
00195     (t_enabled, t_total) = count_enabled_printers(gdb.current_progspace().pretty_printers)
00196     enabled_count += t_enabled
00197     total_count += t_total
00198     for objfile in gdb.objfiles():
00199         (t_enabled, t_total) = count_enabled_printers(objfile.pretty_printers)
00200         enabled_count += t_enabled
00201         total_count += t_total
00202     return (enabled_count, total_count)
00203 
00204 
00205 def pluralize(text, n, suffix="s"):
00206     """Return TEXT pluralized if N != 1."""
00207     if n != 1:
00208         return "%s%s" % (text, suffix)
00209     else:
00210         return text
00211 
00212 
00213 def show_pretty_printer_enabled_summary():
00214     """Print the number of printers enabled/disabled.
00215     We count subprinters individually.
00216     """
00217     (enabled_count, total_count) = count_all_enabled_printers()
00218     print ("%d of %d printers enabled" % (enabled_count, total_count))
00219 
00220 
00221 def do_enable_pretty_printer_1 (pretty_printers, name_re, subname_re, flag):
00222     """Worker for enabling/disabling pretty-printers.
00223 
00224     Arguments:
00225         pretty_printers: list of pretty-printers
00226         name_re: regular-expression object to select printers
00227         subname_re: regular expression object to select subprinters or None
00228                     if all are affected
00229         flag: True for Enable, False for Disable
00230 
00231     Returns:
00232         The number of printers affected.
00233         This is just for informational purposes for the user.
00234     """
00235     total = 0
00236     for printer in pretty_printers:
00237         if (hasattr(printer, "name") and name_re.match(printer.name) or
00238             hasattr(printer, "__name__") and name_re.match(printer.__name__)):
00239             if (hasattr(printer, "subprinters") and
00240                 printer.subprinters is not None):
00241                 if not subname_re:
00242                     # Only record printers that change state.
00243                     if printer_enabled_p(printer) != flag:
00244                         for subprinter in printer.subprinters:
00245                             if printer_enabled_p(subprinter):
00246                                 total += 1
00247                     # NOTE: We preserve individual subprinter settings.
00248                     printer.enabled = flag
00249                 else:
00250                     # NOTE: Whether this actually disables the subprinter
00251                     # depends on whether the printer's lookup function supports
00252                     # the "enable" API.  We can only assume it does.
00253                     for subprinter in printer.subprinters:
00254                         if subname_re.match(subprinter.name):
00255                             # Only record printers that change state.
00256                            if (printer_enabled_p(printer) and
00257                                printer_enabled_p(subprinter) != flag):
00258                                total += 1
00259                            subprinter.enabled = flag
00260             else:
00261                 # This printer has no subprinters.
00262                 # If the user does "disable pretty-printer .* .* foo"
00263                 # should we disable printers that don't have subprinters?
00264                 # How do we apply "foo" in this context?  Since there is no
00265                 # "foo" subprinter it feels like we should skip this printer.
00266                 # There's still the issue of how to handle
00267                 # "disable pretty-printer .* .* .*", and every other variation
00268                 # that can match everything.  For now punt and only support
00269                 # "disable pretty-printer .* .*" (i.e. subname is elided)
00270                 # to disable everything.
00271                 if not subname_re:
00272                     # Only record printers that change state.
00273                     if printer_enabled_p(printer) != flag:
00274                         total += 1
00275                     printer.enabled = flag
00276     return total
00277 
00278 
00279 def do_enable_pretty_printer (arg, flag):
00280     """Internal worker for enabling/disabling pretty-printers."""
00281     (object_re, name_re, subname_re) = parse_printer_regexps(arg)
00282 
00283     total = 0
00284     if object_re.match("global"):
00285         total += do_enable_pretty_printer_1(gdb.pretty_printers,
00286                                             name_re, subname_re, flag)
00287     cp = gdb.current_progspace()
00288     if object_re.match("progspace"):
00289         total += do_enable_pretty_printer_1(cp.pretty_printers,
00290                                             name_re, subname_re, flag)
00291     for objfile in gdb.objfiles():
00292         if object_re.match(objfile.filename):
00293             total += do_enable_pretty_printer_1(objfile.pretty_printers,
00294                                                 name_re, subname_re, flag)
00295 
00296     if flag:
00297         state = "enabled"
00298     else:
00299         state = "disabled"
00300     print ("%d %s %s" % (total, pluralize("printer", total), state))
00301 
00302     # Print the total list of printers currently enabled/disabled.
00303     # This is to further assist the user in determining whether the result
00304     # is expected.  Since we use regexps to select it's useful.
00305     show_pretty_printer_enabled_summary()
00306 
00307 
00308 # Enable/Disable one or more pretty-printers.
00309 #
00310 # This is intended for use when a broken pretty-printer is shipped/installed
00311 # and the user wants to disable that printer without disabling all the other
00312 # printers.
00313 #
00314 # A useful addition would be -v (verbose) to show each printer affected.
00315 
00316 class EnablePrettyPrinter (gdb.Command):
00317     """GDB command to enable the specified pretty-printer.
00318 
00319     Usage: enable pretty-printer [object-regexp [name-regexp]]
00320 
00321     OBJECT-REGEXP is a regular expression matching the objects to examine.
00322     Objects are "global", the program space's file, and the objfiles within
00323     that program space.
00324 
00325     NAME-REGEXP matches the name of the pretty-printer.
00326     Individual printers in a collection are named as
00327     printer-name;subprinter-name.
00328     """
00329 
00330     def __init__(self):
00331         super(EnablePrettyPrinter, self).__init__("enable pretty-printer",
00332                                                    gdb.COMMAND_DATA)
00333 
00334     def invoke(self, arg, from_tty):
00335         """GDB calls this to perform the command."""
00336         do_enable_pretty_printer(arg, True)
00337 
00338 
00339 class DisablePrettyPrinter (gdb.Command):
00340     """GDB command to disable the specified pretty-printer.
00341 
00342     Usage: disable pretty-printer [object-regexp [name-regexp]]
00343 
00344     OBJECT-REGEXP is a regular expression matching the objects to examine.
00345     Objects are "global", the program space's file, and the objfiles within
00346     that program space.
00347 
00348     NAME-REGEXP matches the name of the pretty-printer.
00349     Individual printers in a collection are named as
00350     printer-name;subprinter-name.
00351     """
00352 
00353     def __init__(self):
00354         super(DisablePrettyPrinter, self).__init__("disable pretty-printer",
00355                                                    gdb.COMMAND_DATA)
00356 
00357     def invoke(self, arg, from_tty):
00358         """GDB calls this to perform the command."""
00359         do_enable_pretty_printer(arg, False)
00360 
00361 
00362 def register_pretty_printer_commands():
00363     """Call from a top level script to install the pretty-printer commands."""
00364     InfoPrettyPrinter()
00365     EnablePrettyPrinter()
00366     DisablePrettyPrinter()
00367 
00368 register_pretty_printer_commands()
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines