This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
RFC: enum pretty-printing support
- From: Tom Tromey <tromey at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Tue, 10 Jan 2012 12:54:39 -0700
- Subject: RFC: enum pretty-printing support
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 <tromey@redhat.com>
PR python/13281:
* python/lib/gdb/printing.py (_EnumInstance): New class.
(EnumerationPrinter): Likewise.
b/gdb/doc/ChangeLog:
2012-01-10 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (gdb.printing): Document EnumerationPrinter.
b/gdb/testsuite/ChangeLog:
2012-01-10 Tom Tromey <tromey@redhat.com>
* 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('<unknown: 0x%x>' % 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 <string.h>
+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=<a=<1> b=<$hex>> b=<a=<2> 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=<a=<1> b=<$hex>> b=<a=<2> 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 | <unknown: 0x8>." \
+ "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