This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] new commands: info pretty-printers, enable/disable pretty-printer


Hi.

This patch provides a convention for naming pretty printers,
adds support for the common case of using a regexp on the type name,
and adds 3 new commands, written in python:

info pretty-printers [obj-regexp [name-regexp [subname-regexp]]]
enable pretty-printer [obj-regexp [name-regexp [subname-regexp]]]
disable pretty-printer [obj-regexp [name-regexp [subname-regexp]]]

obj-regexp is used to denote which pretty-printer list:
gdb, current-progspace, or objfile.
name-regexp is the name of the pretty-printer, e.g. for libstdc++
it could be "libstdc++".
subname-regexp is there because one "pretty-printer" can print an
arbitrary number of types.

This is just a strawman.  [No NEWS, docs, this is just RFC.]
How *do* we want this to work, if at all?
Comments?


The testcase punts on testing this when build != host.
The preferred way of testing this is to set up a python module library
on the [possibly) remote host, but I can't find support in dejagnu for
setting up directories on the remote host (perhaps I missed it of course).

Example from the testcase:

(gdb) info pretty-printers
global pretty-printers:
    pp-test
      ^struct s$
      ^s$
      ^struct ss$
      ^ss$
(gdb) disable pretty-printer global pp-test .*
4 printers disabled
0 printers enabled, 4 total printers
(gdb) enable pretty-printer global pp-test .*
4 printers enabled
4 printers enabled, 4 total printers

[The output of `enable' is a bit klunky, I figure that's the least
of my worries ...]


2010-06-08  Doug Evans  <dje@google.com>

	Give pretty-printers names.  Add new commands:
	info pretty-printers, enable|disable pretty-printer
	* python/lib/gdb/printing.py: New file.

	testsuite/
	* gdb.python/py-pp-maint.c: New file.
	* gdb.python/py-pp-maint.py: New file.
	* gdb.python/py-pp-maint.exp: New file.

Index: python/lib/gdb/printing.py
===================================================================
RCS file: python/lib/gdb/printing.py
diff -N python/lib/gdb/printing.py
--- /dev/null	2009-04-24 06:57:12.000000000 -0700
+++ python/lib/gdb/printing.py	2010-06-08 10:46:41.000000000 -0700
@@ -0,0 +1,421 @@
+# Pretty-printer utilities.
+
+import gdb
+import re
+
+# Given a type, return the same type with references, typedefs and qualifiers
+# (const, volatile) stripped away.
+
+def get_base_type (val):
+    """Helper function: return 'base' type of VAL"""
+
+    tp = val.type
+    if tp.code == gdb.TYPE_CODE_REF:
+        tp = tp.target ()
+    tp = tp.unqualified ().strip_typedefs ()
+    return tp
+
+# A basic pretty-printer.
+#
+# `name' is a unique string among all printers for the context in which
+# it is defined (objfile, progspace, or global(gdb)), and should meaningfully
+# describe what can be pretty-printed.  E.g., "StringPiece" or "protobufs".
+# `lookup' is a function of one argument: The value to be pretty-printed.
+# If `subprinters' is non-None, it must be an iterable object with each
+# element having a `name' attribute, and, potentially, "enabled" attribute.
+
+class PrettyPrinter (object):
+    def __init__ (self, name, lookup, subprinters=None):
+        self.name = name
+        self.lookup = lookup
+        self.subprinters = subprinters
+        # True if this printer is enabled.
+        self.enabled = True
+
+    # "new-style" classes need __call__ to be defined in the class,
+    # not in an instance.  i.e. we can't do "self.__call__ = lookup"
+    # in __init__.
+    # http://docs.python.org/reference/datamodel.html#special-method-lookup-for-new-style-classes
+    def __call__ (self, val):
+        return self.lookup (self, val)
+
+# Baseclass for sub-pretty-printers.
+# Sub-pretty-printers needn't use this, but it formalizes what's needed.
+
+class SubPrettyPrinter (object):
+    def __init__ (self, name):
+        self.name = name
+        self.enabled = True
+
+# Add `printer' to the list of pretty-printers for `obj'.
+#
+# `printer' is either a function of one argument (old way) or any object which
+# has the `__call__' attribute.
+# In addition, if the caller wants the printer to be listable and disableable,
+# it must follow the PrettyPrinter API.
+# __call__ is a function of one argument: The value to be pretty-printed.
+# If you wish to make other state available to __call__, e.g., the list of
+# subprinters, you must create a closure.
+#
+# `obj' is either an objfile, progspace, or None (in which case the printer
+# is registered globally).
+
+def register_pretty_printer (obj, printer):
+    """Register pretty-printer PRINTER with OBJ."""
+
+    if not hasattr (printer, "name"):
+        raise "Printer missing attribute: name"
+    if not hasattr (printer, "__call__"):
+        raise "Printer missing attribute: __call__"
+    if obj == None:
+        if gdb.parameter ("verbose"):
+            gdb.write ("Registering global %s pretty-printer ...\n"
+                       % printer.name)
+        obj = gdb
+    else:
+        if gdb.parameter ("verbose"):
+            gdb.write ("Registering %s pretty-printer for %s ...\n"
+                       % (printer.name, obj.filename))
+
+    if hasattr (printer, "name"):
+        # First make sure the printer's name is unique.
+        # PERF: gdb records printers in a list, making this inefficient.
+        if printer.name in map (lambda p: p.name, obj.pretty_printers):
+            raise "pretty-printer already registered: %s" % printer.name
+
+    obj.pretty_printers.append (printer)
+
+# Utility to parse a command argv of
+# [object-regexp [name-regexp [subname-regexp]]].
+# The result is a 3-tuple of compiled regular expressions, except that
+# the resulting compiled subname regexp is None if not provided.
+#
+# If there's an error processing ARG, gdb.GdbError is thrown.
+
+def parse_printer_regexps (arg):
+    argv = gdb.string_to_argv (arg);
+    argc = len (argv)
+    object_regexp = "" # match everything
+    name_regexp = "" # match everything
+    subname_regexp = None
+    if (argc > 3):
+        gdb.GdbError.__str__ = None
+        raise gdb.GdbError
+        #raise gdb.GdbError ("Too many arguments")
+        #raise "Too many arguments", "fubar"
+    if argc >= 1:
+        object_regexp = argv[0]
+    if argc >= 2:
+        name_regexp = argv[1]
+    if argc >= 3:
+        subname_regexp = argv[2]
+    try:
+        object_re = re.compile (object_regexp)
+    except:
+        raise gdb.GdbError ("invalid object regexp: %s" % object_regexp)
+    try:
+        name_re = re.compile (name_regexp)
+    except:
+        raise gdb.GdbError ("invalid name regexp: %s" % name_regexp)
+    if subname_regexp != None:
+        try:
+            subname_re = re.compile (subname_regexp)
+        except:
+            raise gdb.GdbError ("invalid subname regexp: %s" % subname_regexp)
+    else:
+        subname_re = None
+    return (object_re, name_re, subname_re)
+
+# Internal utility to return True if PRINTER is enabled, False if disabled.
+# PRINTER is either a printer or subprinter.
+
+def printer_enabled_p (printer):
+    if hasattr (printer, "enabled"):
+        if printer.enabled:
+            return True
+        else:
+            return False
+    else:
+        return True
+
+# Class to implement the "info pretty-printers" command.
+
+class InfoPrettyPrinters (gdb.Command):
+    """List all registered pretty-printers.
+    Usage: info pretty-printers [object-regexp [name-regexp [subname-regexp]]]
+    OBJECT-REGEXP is a regular expression matching the objects to list.
+    Objects are "global", the program space's file, and the objfiles within
+    that program space.
+    NAME-REGEXP matches the name of the pretty-printer.
+    SUBNAME-REGEXP matches the name of the subprinter."""
+
+    def __init__ (self):
+        super (InfoPrettyPrinters, self).__init__ ("info pretty-printers",
+                                                   gdb.COMMAND_DATA)
+
+    # Return "" if PRINTER is enabled, otherwise " [disabled]".
+
+    def enabled_string (self, printer):
+        if printer_enabled_p (printer):
+            return ""
+        else:
+            return " [disabled]"
+
+    # Internal utility to print a list of pretty-printers.
+
+    def list_pretty_printers (self, pretty_printers, name_re, subname_re):
+        for printer in pretty_printers:
+            enabled = self.enabled_string (printer)
+            if hasattr (printer, "name"):
+                if name_re.match (printer.name):
+                    print "    %s%s" % (printer.name, enabled)
+                    if hasattr (printer, "subprinters") \
+                          and printer.subprinters != None:
+                        for subprinter in printer.subprinters:
+                            if subname_re == None \
+                                  or subname_re.match (subprinter.name):
+                                print "      %s%s" % (subprinter.name,
+                                                      self.enabled_string (subprinter))
+            else:
+                if name_re.match ("unknown"):
+                    print "    unknown printer: %s%s" % (printer, enabled)
+
+    def invoke (self, arg, from_tty):
+        (object_re, name_re, subname_re) = parse_printer_regexps (arg)
+        if len (gdb.pretty_printers) > 0 \
+              and object_re.match ("global"):
+            print "global pretty-printers:"
+            self.list_pretty_printers (gdb.pretty_printers,
+                                       name_re, subname_re)
+        cp = gdb.current_progspace ()
+        if len (cp.pretty_printers) > 0 \
+              and object_re.match (cp.filename):
+            print "progspace %s pretty-printers:" % cp.filename
+            self.list_pretty_printers (cp.pretty_printers,
+                                       name_re, subname_re)
+        for objfile in gdb.objfiles ():
+            if len (objfile.pretty_printers) > 0 \
+                  and object_re.match (objfile.filename):
+                print "  objfile %s pretty-printers:" % objfile.filename
+                self.list_pretty_printers (objfile.pretty_printers,
+                                           name_re, subname_re)
+
+# Return a 2-tuple of number of enabled and total printers in PRETTY_PRINTERS.
+
+def count_enabled_printers (pretty_printers):
+    enabled = 0
+    total = 0
+    for printer in pretty_printers:
+        if hasattr (printer, "subprinters") \
+              and printer.subprinters != None:
+            if printer_enabled_p (printer):
+                for subprinter in printer.subprinters:
+                    if printer_enabled_p (subprinter):
+                        enabled += 1
+            total += len (printer.subprinters)
+        else:
+            if printer_enabled_p (printer):
+                enabled += 1
+            total += 1
+    return (enabled, total)
+
+# Return a 2-tuble of the enabled state and total number of all printers,
+# including subprinters.
+
+def count_all_enabled_printers ():
+    enabled_count = 0
+    total_count = 0
+    (t_enabled, t_total) = count_enabled_printers (gdb.pretty_printers)
+    enabled_count += t_enabled
+    total_count += t_total
+    (t_enabled, t_total) = count_enabled_printers (gdb.current_progspace ().pretty_printers)
+    enabled_count += t_enabled
+    total_count += t_total
+    for objfile in gdb.objfiles ():
+        (t_enabled, t_total) = count_enabled_printers (objfile.pretty_printers)
+        enabled_count += t_enabled
+        total_count += t_total
+    return (enabled_count, total_count)
+
+# Internal utility to return TEXT pluralized if N != 1.
+
+def pluralize (text, n, suffix="s"):
+    if n != 1:
+        return "%s%s" % (text, suffix)
+    else:
+        return text
+    
+# Print the number of printers enabled/disabled.
+# We count subprinters individually.
+
+def show_pretty_printer_enabled_summary ():
+    (enabled_count, total_count) = count_all_enabled_printers ()
+    print "%d %s enabled, %d total %s" \
+        % (enabled_count, pluralize ("printer", enabled_count),
+           total_count, pluralize ("printer", total_count))
+
+# Internal worker for enabling/disabling pretty-printers.
+# PRETTY_PRINTERS is a list of pretty-printers.
+# NAME_RE is a regular-expression object to select printers.
+# SUBNAME_RE is a regular expression object to select subprinters or None
+# if all are affected.
+# FLAG is True for Enable, False for Disable.
+#
+# The result is the number of printers affected.
+# This is just for informational purposes for the user.
+
+def do_enable_pretty_printer_1 (pretty_printers, name_re, subname_re, flag):
+    total = 0
+    for printer in pretty_printers:
+        if hasattr (printer, "name") and name_re.match (printer.name):
+            if hasattr (printer, "subprinters"):
+                if subname_re == None:
+                    # NOTE: We preserve individual subprinter settings.
+                    printer.enabled = flag
+                    total += len (printer.subprinters)
+                else:
+                    # NOTE: Whether this actually disables the subprinter
+                    # depends on whether the printer's lookup_function supports
+                    # the "enable" API.  We can only assume it does.
+                    for subprinter in printer.subprinters:
+                        if subname_re.match (subprinter.name):
+                            subprinter.enabled = flag
+                            total += 1
+            else:
+                # This printer has no subprinters.
+                # If the user does "disable pretty-printer .* .* foo"
+                # should we disable printers that don't have subprinters?
+                # How do we apply "foo" in this context?  Since there is no
+                # "foo" subprinter it feels like we should skip this printer.
+                # There's still the issue of how to handle
+                # "disable pretty-printer .* .* .*", and every other variation
+                # that can match everything.  For now punt and only support
+                # "disable pretty-printer .* .*" (i.e. subname is elided)
+                # to disable everything.
+                if subname_re == None:
+                    printer.enabled = flag
+                    total += 1
+    return total
+
+# Internal worker for enabling/disabling pretty-printers.
+
+def do_enable_pretty_printer (arg, flag):
+    (object_re, name_re, subname_re) = parse_printer_regexps (arg)
+
+    total = 0
+    if object_re.match ("global"):
+        total += do_enable_pretty_printer_1 (gdb.pretty_printers,
+                                             name_re, subname_re, flag)
+    cp = gdb.current_progspace ()
+    if object_re.match (cp.filename):
+        total += do_enable_pretty_printer_1 (cp.pretty_printers,
+                                             name_re, subname_re, flag)
+    for objfile in gdb.objfiles ():
+        if object_re.match (objfile.filename):
+            total += do_enable_pretty_printer_1 (objfile.pretty_printers,
+                                                 name_re, subname_re, flag)
+
+    if flag:
+        state = "enabled"
+    else:
+        state = "disabled"
+    print "%d %s %s" % (total, pluralize ("printer", total), state)
+
+    # Print the total list of printers currently enabled/disabled.
+    # This is to further assist the user in determining whether the result
+    # is expected.  Since we use regexps to select it's useful.
+    show_pretty_printer_enabled_summary ()
+
+# Enable/Disable one or more pretty-printers.
+#
+# This is intended for use when a broken pretty-printer is shipped/installed
+# and the user wants to disable that printer without disabling all the other
+# printers.
+#
+# A useful addition would be -v (verbose) to show each printer affected.
+
+class EnablePrettyPrinter (gdb.Command):
+    """Enable the specified pretty-printer.
+    Usage: enable pretty-printer [object-regexp [name-regexp [subname-regexp]]]
+    OBJECT-REGEXP is a regular expression matching the objects to examine.
+    Objects are "global", the program space's file, and the objfiles within
+    that program space.
+    NAME-REGEXP matches the name of the pretty-printer.
+    SUBNAME-REGEXP matches the name of the subprinter."""
+
+    def __init__ (self):
+        super (EnablePrettyPrinter, self).__init__ ("enable pretty-printer",
+                                                    gdb.COMMAND_DATA)
+
+    def invoke (self, arg, from_tty):
+        do_enable_pretty_printer (arg, True)
+
+class DisablePrettyPrinter (gdb.Command):
+    """Disable the specified pretty-printer.
+    Usage: disable pretty-printer [object-regexp [name-regexp [subname-regexp]]]
+    OBJECT-REGEXP is a regular expression matching the objects to examine.
+    Objects are "global", the program space's file, and the objfiles within
+    that program space.
+    NAME-REGEXP matches the name of the pretty-printer.
+    SUBNAME-REGEXP matches the name of the subprinter."""
+
+    def __init__ (self):
+        super (DisablePrettyPrinter, self).__init__ ("disable pretty-printer",
+                                                     gdb.COMMAND_DATA)
+
+    def invoke (self, arg, from_tty):
+        do_enable_pretty_printer (arg, False)
+
+# Internal class for implementing regular-expression based pretty-printers.
+
+class RePrettyPrinter (SubPrettyPrinter):
+    def __init__ (self, regexp, gen_printer):
+        super (RePrettyPrinter, self).__init__ (regexp)
+        self.compiled_re = re.compile (regexp)
+        self.gen_printer = gen_printer
+
+# Utility for building a regular-expression based lookup table.
+# REGEXP is the regular expression, as a string.
+# GEN_PRINTER is a function that returns the pretty-printed form of its
+# argument.
+
+def add_re_printer (table, regexp, gen_printer):
+  table.append (RePrettyPrinter (regexp, gen_printer))
+
+# Standard lookup_function for regular-expression based pretty-printers.
+#
+# NOTE: This cannot be passed to register_pretty_printer "as is".
+# It is intended to be used as the "lookup" parameter of PrettyPrinter.
+# Normally this is used by calling register_pretty_printer as:
+#
+# pretty_printers_list = []
+# add_re_printer (pretty_printers_list, ...)
+# ...
+# add_re_printer (pretty_printers_list, ...)
+# register_pretty_printer (obj,
+#                          PrettyPrinter ("libstdc++",
+#                                         re_lookup_function,
+#                                         pretty_printers_list))
+
+def re_lookup_function (printer_object, val):
+    # Get the type name.
+    typename = get_base_type (val).tag
+    if typename == None:
+        return None
+
+    # Iterate over table of type regexps to determine
+    # if a printer is registered for that type.
+    # Return an instantiation of the printer if found.
+    for printer in printer_object.subprinters:
+        if printer.enabled and printer.compiled_re.search (typename):
+            return printer.gen_printer (val)
+
+    # Cannot find a pretty printer.  Return None.
+    return None
+
+# Call from a top level script to install the pretty-printer commands.
+
+def register_pretty_printer_commands ():
+    InfoPrettyPrinters ()
+    EnablePrettyPrinter ()
+    DisablePrettyPrinter ()
Index: testsuite/gdb.python/py-pp-maint.c
===================================================================
RCS file: testsuite/gdb.python/py-pp-maint.c
diff -N testsuite/gdb.python/py-pp-maint.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/py-pp-maint.c	8 Jun 2010 18:50:05 -0000
@@ -0,0 +1,54 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+
+struct s
+{
+  int a;
+  int *b;
+};
+
+struct ss
+{
+  struct s a;
+  struct s b;
+};
+
+void
+init_s (struct s *s, int a)
+{
+  s->a = a;
+  s->b = &s->a;
+}
+
+void
+init_ss (struct ss *s, int a, int b)
+{
+  init_s (&s->a, a);
+  init_s (&s->b, b);
+}
+
+int
+main ()
+{
+  struct ss ss;
+
+  init_ss (&ss, 1, 2);
+  
+  return 0;      /* break to inspect */
+}
Index: testsuite/gdb.python/py-pp-maint.exp
===================================================================
RCS file: testsuite/gdb.python/py-pp-maint.exp
diff -N testsuite/gdb.python/py-pp-maint.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/py-pp-maint.exp	8 Jun 2010 18:50:05 -0000
@@ -0,0 +1,82 @@
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests Python-based
+# pretty-printing for the CLI.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+if [is_remote host] {
+    untested "py-pp-maint.exp can only be run locally"
+    return -1
+}
+
+set testfile "py-pp-maint"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# Start with a fresh gdb.
+gdb_exit
+gdb_start
+
+# Skip all tests if Python scripting is not enabled.
+if { [skip_python_tests] } { continue }
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug"] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main ] then {
+    perror "couldn't run to breakpoint"
+    return
+}
+
+set gdb_python_dir [file normalize ${srcdir}/../python/lib]
+gdb_test_no_output "python sys.path.insert (0, '${gdb_python_dir}')"
+gdb_test_no_output "python gdb.__path__ = \[ '${gdb_python_dir}/gdb' \]"
+gdb_test_no_output "python from gdb.printing import register_pretty_printer_commands"
+gdb_test_no_output "python register_pretty_printer_commands ()"
+
+gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \
+    ".*Breakpoint.*"
+gdb_test "continue" ".*Breakpoint.*"
+
+set python_file ${srcdir}/${subdir}/${testfile}.py
+
+gdb_test_no_output "python execfile ('${python_file}')" ""
+
+gdb_test "info pretty-printers" \
+    {.*pp-test.*struct ss.*}
+
+gdb_test "print ss" " = a=< a=<1> b=<$hex>> b=< a=<2> b=<$hex>>" \
+    "print ss enabled #1"
+
+gdb_test "disable pretty-printer global pp-test .*" \
+    "4 printers disabled.*"
+
+gdb_test "print ss" " = {a = {a = 1, b = $hex}, b = {a = 2, b = $hex}}" \
+    "print ss disabled"
+
+gdb_test "enable pretty-printer global pp-test .*" \
+    "4 printers enabled.*"
+
+gdb_test "print ss" " = a=< a=<1> b=<$hex>> b=< a=<2> b=<$hex>>" \
+    "print ss enabled #2"
Index: testsuite/gdb.python/py-pp-maint.py
===================================================================
RCS file: testsuite/gdb.python/py-pp-maint.py
diff -N testsuite/gdb.python/py-pp-maint.py
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/py-pp-maint.py	8 Jun 2010 18:50:05 -0000
@@ -0,0 +1,55 @@
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests python pretty
+# printers.
+
+import re
+from gdb.printing import add_re_printer
+
+class pp_s:
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        a = self.val["a"]
+        b = self.val["b"]
+        if a.address != b:
+            raise Exception("&a(%s) != b(%s)" % (str(a.address), str(b)))
+        return " a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
+
+class pp_ss:
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        return "a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
+
+def build_pretty_printers ():
+    pp_list = []
+
+    add_re_printer (pp_list, '^struct s$', pp_s)
+    add_re_printer (pp_list, '^s$', pp_s)
+
+    add_re_printer (pp_list, '^struct ss$', pp_ss)
+    add_re_printer (pp_list, '^ss$', pp_ss)
+
+    return pp_list
+
+pretty_printers_list = build_pretty_printers ()
+gdb.printing.register_pretty_printer (gdb,
+    gdb.printing.PrettyPrinter ("pp-test",
+                                gdb.printing.re_lookup_function,
+                                pretty_printers_list))


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]