From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 726 invoked by alias); 10 Jan 2012 19:55:00 -0000 Received: (qmail 717 invoked by uid 22791); 10 Jan 2012 19:54:58 -0000 X-SWARE-Spam-Status: No, hits=-7.0 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 10 Jan 2012 19:54:41 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0AJsfAR011696 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 10 Jan 2012 14:54:41 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q0AJsepv017543; Tue, 10 Jan 2012 14:54:40 -0500 Received: from barimba (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id q0AJsd6F028366; Tue, 10 Jan 2012 14:54:39 -0500 From: Tom Tromey To: gdb-patches@sourceware.org Subject: RFC: enum pretty-printing support Date: Tue, 10 Jan 2012 20:26:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-01/txt/msg00308.txt.bz2 I'd appreciate comments on this patch. This adds a new helper class to gdb.printing to handle printing of enum values which are or'd together. E.g.: print (enum flag_enum) (FLAG_1 | FLAG_3) $8 = 0x5 [FLAG_1 | FLAG_3] Tom b/gdb/ChangeLog: 2012-01-10 Tom Tromey PR python/13281: * python/lib/gdb/printing.py (_EnumInstance): New class. (EnumerationPrinter): Likewise. b/gdb/doc/ChangeLog: 2012-01-10 Tom Tromey * gdb.texinfo (gdb.printing): Document EnumerationPrinter. b/gdb/testsuite/ChangeLog: 2012-01-10 Tom Tromey * gdb.python/py-pp-maint.py (build_pretty_printer): Instantiate EnumerationPrinter. * gdb.python/py-pp-maint.exp: Add tests for EnumerationPrinter. * gdb.python/py-pp-maint.c (enum flag_enum): New. (fval): New global. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 853692c..3896bf1 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -24380,6 +24380,13 @@ Utility class for handling multiple printers, all recognized via regular expressions. @xref{Writing a Pretty-Printer}, for an example. +@item EnumerationPrinter (@var{name}) +A pretty-printer which handles printing of @code{enum} values. Unlike +@value{GDBN}'s built-in @code{enum} printing, this printer handles the +case where enumerators are or'd together to create a value. +@var{name} is the name of the printer and also the name of the +@code{enum} type to look up. + @item register_pretty_printer (@var{obj}, @var{printer}, @var{replace}=False) Register @var{printer} with the pretty-printer list of @var{obj}. If @var{replace} is @code{True} then any existing copy of the printer diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py index a030827..52089a3 100644 --- a/gdb/python/lib/gdb/printing.py +++ b/gdb/python/lib/gdb/printing.py @@ -206,3 +206,47 @@ class RegexpCollectionPrettyPrinter(PrettyPrinter): # Cannot find a pretty printer. Return None. return None + +# A helper class for printing enum types. This class is instantiated +# with a list of enumerators to print a particular Value. +class _EnumInstance: + def __init__(self, enumerators, val): + self.enumerators = enumerators + self.val = val + + def to_string(self): + flag_list = [] + v = long(self.val) + for (e_name, e_value) in self.enumerators: + if v & e_value != 0: + flag_list.append(e_name) + # We assume the enumerators are exclusive. + v = v & ~e_value + if v != 0: + # Leftover value. + flag_list.append('' % v) + return "0x%x [%s]" % (self.val, " | ".join(flag_list)) + +class EnumerationPrinter(PrettyPrinter): + """A pretty-printer which can be used to print a flag-style enumeration. + A flag-style enumeration is one where the enumerators are or'd + together to create values. The new printer will print these + symbolically using '|' notation. The printer must be registered + manually.""" + + def __init__(self, enum_type): + super(EnumerationPrinter, self).__init__(enum_type) + self.initialized = False + + def __call__(self, val): + if not self.initialized: + self.initialized = True + flags = gdb.lookup_type(self.name) + self.enumerators = [] + for field in flags.fields(): + self.enumerators.append((field.name, field.bitpos)) + + if self.enabled: + return _EnumInstance(self.enumerators, val) + else: + return None diff --git a/gdb/testsuite/gdb.python/py-pp-maint.c b/gdb/testsuite/gdb.python/py-pp-maint.c index d9b0fa0..3e4aa24 100644 --- a/gdb/testsuite/gdb.python/py-pp-maint.c +++ b/gdb/testsuite/gdb.python/py-pp-maint.c @@ -17,6 +17,15 @@ #include +enum flag_enum + { + FLAG_1 = 1, + FLAG_2 = 2, + FLAG_3 = 4 + }; + +enum flag_enum fval; + struct function_lookup_test { int x,y; diff --git a/gdb/testsuite/gdb.python/py-pp-maint.exp b/gdb/testsuite/gdb.python/py-pp-maint.exp index ce88ca5..cc8777a 100644 --- a/gdb/testsuite/gdb.python/py-pp-maint.exp +++ b/gdb/testsuite/gdb.python/py-pp-maint.exp @@ -74,23 +74,25 @@ gdb_test "print flt" " = x=<42> y=<43>" \ gdb_test "print ss" " = a= b=<$hex>> b= b=<$hex>>" \ "print ss enabled #1" +set num_pp 6 + gdb_test "disable pretty-printer" \ - "5 printers disabled.*0 of 5 printers enabled" + "$num_pp printers disabled.*0 of $num_pp printers enabled" gdb_test "enable pretty-printer" \ - "5 printers enabled.*5 of 5 printers enabled" + "$num_pp printers enabled.*$num_pp of $num_pp printers enabled" gdb_test "disable pretty-printer global" \ - "5 printers disabled.*0 of 5 printers enabled" + "$num_pp printers disabled.*0 of $num_pp printers enabled" gdb_test "enable pretty-printer" \ - "5 printers enabled.*5 of 5 printers enabled" + "$num_pp printers enabled.*$num_pp of $num_pp printers enabled" gdb_test "disable pretty-printer global lookup_function_lookup_test" \ - "1 printer disabled.*4 of 5 printers enabled" + "1 printer disabled.*[expr $num_pp - 1] of $num_pp printers enabled" gdb_test "disable pretty-printer global pp-test;.*" \ - "4 printers disabled.*0 of 5 printers enabled" + "[expr $num_pp - 1] printers disabled.*0 of $num_pp printers enabled" gdb_test "info pretty-printer global .*function" \ {.*function_lookup_test \[disabled\].*} @@ -105,19 +107,22 @@ gdb_test "print ss" " = {a = {a = 1, b = $hex}, b = {a = 2, b = $hex}}" \ "print ss disabled" gdb_test "enable pretty-printer global lookup_function_lookup_test" \ - "1 printer enabled.*1 of 5 printers enabled" + "1 printer enabled.*1 of $num_pp printers enabled" # This doesn't enable any printers because each subprinter in the collection # is still individually disabled. But this is still needed, to enable the # collection itself. gdb_test "enable pretty-printer global pp-test" \ - "0 printers enabled.*1 of 5 printers enabled" + "0 printers enabled.*1 of $num_pp printers enabled" gdb_test "enable pretty-printer global pp-test;.*ss.*" \ - "2 printers enabled.*3 of 5 printers enabled" + "2 printers enabled.*[expr $num_pp - 3] of $num_pp printers enabled" gdb_test "enable pretty-printer global pp-test;.*s.*" \ - "2 printers enabled.*5 of 5 printers enabled" + "2 printers enabled.*[expr $num_pp - 1] of $num_pp printers enabled" + +gdb_test "enable pretty-printer global pp-test;.*" \ + "1 printer enabled.*$num_pp of $num_pp printers enabled" gdb_test "info pretty-printer" \ {.*function_lookup_test.*pp-test.*struct ss.*} @@ -127,3 +132,18 @@ gdb_test "print flt" " = x=<42> y=<43>" \ gdb_test "print ss" " = a= b=<$hex>> b= b=<$hex>>" \ "print ss re-enabled" + +gdb_test "print (enum flag_enum) (FLAG_1)" \ + " = 0x1 .FLAG_1." \ + "print FLAG_1" + +gdb_test "print (enum flag_enum) (FLAG_1 | FLAG_3)" \ + " = 0x5 .FLAG_1 | FLAG_3." \ + "print FLAG_1 | FLAG_3" + +gdb_test "print (enum flag_enum) (4 + 8)" \ + " = 0xc .FLAG_1 | ." \ + "print FLAG_1 | 8" + + + diff --git a/gdb/testsuite/gdb.python/py-pp-maint.py b/gdb/testsuite/gdb.python/py-pp-maint.py index c35d1dc..3df11ea 100644 --- a/gdb/testsuite/gdb.python/py-pp-maint.py +++ b/gdb/testsuite/gdb.python/py-pp-maint.py @@ -67,6 +67,9 @@ def build_pretty_printer(): pp.add_printer('struct ss', '^struct ss$', lambda val: pp_ss(val)) pp.add_printer('ss', '^ss$', lambda val: pp_ss(val)) + pp.add_printer('enum flag_enum', '^flag_enum$', + gdb.printing.EnumerationPrinter('enum flag_enum')) + return pp