* RFC: enum pretty-printing support @ 2012-01-10 20:26 Tom Tromey 2012-01-10 20:28 ` Pedro Alves ` (2 more replies) 0 siblings, 3 replies; 13+ messages in thread From: Tom Tromey @ 2012-01-10 20:26 UTC (permalink / raw) To: gdb-patches 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 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-10 20:26 RFC: enum pretty-printing support Tom Tromey @ 2012-01-10 20:28 ` Pedro Alves 2012-01-11 16:45 ` Tom Tromey 2012-01-10 21:19 ` Eli Zaretskii 2012-01-10 21:23 ` Jan Kratochvil 2 siblings, 1 reply; 13+ messages in thread From: Pedro Alves @ 2012-01-10 20:28 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches On 01/10/2012 07:54 PM, Tom Tromey wrote: > 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] I think this is great. On 01/10/2012 07:54 PM, Tom Tromey wrote: > +@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. Is the intention to have this printer do more than work with flag enums? Otherwise, I'd suggest naming it FlagEnumerationPrinter (or some such). -- Pedro Alves ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-10 20:28 ` Pedro Alves @ 2012-01-11 16:45 ` Tom Tromey 0 siblings, 0 replies; 13+ messages in thread From: Tom Tromey @ 2012-01-11 16:45 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches >>>>> "Pedro" == Pedro Alves <alves.ped@gmail.com> writes: Pedro> Is the intention to have this printer do more than work Pedro> with flag enums? Otherwise, I'd suggest naming it FlagEnumerationPrinter Pedro> (or some such). I made this change. Thanks. Tom ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-10 20:26 RFC: enum pretty-printing support Tom Tromey 2012-01-10 20:28 ` Pedro Alves @ 2012-01-10 21:19 ` Eli Zaretskii 2012-01-10 21:23 ` Jan Kratochvil 2 siblings, 0 replies; 13+ messages in thread From: Eli Zaretskii @ 2012-01-10 21:19 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches > From: Tom Tromey <tromey@redhat.com> > Date: Tue, 10 Jan 2012 12:54:39 -0700 > > b/gdb/doc/ChangeLog: > 2012-01-10 Tom Tromey <tromey@redhat.com> > > * gdb.texinfo (gdb.printing): Document EnumerationPrinter. This part is fine, thanks. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-10 20:26 RFC: enum pretty-printing support Tom Tromey 2012-01-10 20:28 ` Pedro Alves 2012-01-10 21:19 ` Eli Zaretskii @ 2012-01-10 21:23 ` Jan Kratochvil 2012-01-10 22:00 ` Tom Tromey 2 siblings, 1 reply; 13+ messages in thread From: Jan Kratochvil @ 2012-01-10 21:23 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches On Tue, 10 Jan 2012 20:54:39 +0100, Tom Tromey wrote: > I'd appreciate comments on this patch. There is the obvious question this may work automatically if all the values of enum type are in the form 2^n and fall back to the GDB default way otherwise. Also it would not display parentheses if the variable value is just 2^n. GDB could pass the type as `enum NAME' instead of just `NAME' to the pretty printer regex. Thanks, Jan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-10 21:23 ` Jan Kratochvil @ 2012-01-10 22:00 ` Tom Tromey 2012-01-10 22:19 ` Tom Tromey 0 siblings, 1 reply; 13+ messages in thread From: Tom Tromey @ 2012-01-10 22:00 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes: Jan> On Tue, 10 Jan 2012 20:54:39 +0100, Tom Tromey wrote: >> I'd appreciate comments on this patch. Jan> There is the obvious question this may work automatically if all Jan> the values of enum type are in the form 2^n and fall back to the Jan> GDB default way otherwise. Yeah, that might be nicer. I will look into it. Jan> GDB could pass the type as `enum NAME' instead of just `NAME' to Jan> the pretty printer regex. I thought perhaps the user would want to register it against a typedef as well. Tom ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-10 22:00 ` Tom Tromey @ 2012-01-10 22:19 ` Tom Tromey 2012-01-10 23:52 ` Jan Kratochvil 0 siblings, 1 reply; 13+ messages in thread From: Tom Tromey @ 2012-01-10 22:19 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches Jan> There is the obvious question this may work automatically if all Jan> the values of enum type are in the form 2^n and fall back to the Jan> GDB default way otherwise. Tom> Yeah, that might be nicer. Tom> I will look into it. I think the basic code is pretty easy to write. I have it written, but I can't test it until tomorrow. I do wonder whether we still want the Python code. My C implementation works by checking whether the enum values are disjoint. However, it is not uncommon to see things like: enum flags { ONE = 1, TWO = 2, HIGHEST = TWO }; or enum flags { ONE = 1, TWO = 2, ALL = ONE | TWO }; ... but the Python code would acceptably handle both of these. This was ok for the Python approach because registration is explicit, not implicit; I think the C code has to be a bit more careful because it cannot readily be turned off. One idea is to have both. Tom ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-10 22:19 ` Tom Tromey @ 2012-01-10 23:52 ` Jan Kratochvil 2012-01-11 16:46 ` Tom Tromey 0 siblings, 1 reply; 13+ messages in thread From: Jan Kratochvil @ 2012-01-10 23:52 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches On Tue, 10 Jan 2012 23:09:06 +0100, Tom Tromey wrote: > I think the C code has to be a bit more careful because it > cannot readily be turned off. > > One idea is to have both. I agree. Thanks, Jan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-10 23:52 ` Jan Kratochvil @ 2012-01-11 16:46 ` Tom Tromey 2012-01-11 21:03 ` Jan Kratochvil 0 siblings, 1 reply; 13+ messages in thread From: Tom Tromey @ 2012-01-11 16:46 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches Tom> I think the C code has to be a bit more careful because it Tom> cannot readily be turned off. Tom> Tom> One idea is to have both. Jan> I agree. Here's a new patch. Let me know what you think. This adds basic flag enum printing to c-valprint.c. I looked at other languages, but I don't know their syntax enough to say whether this same approach is ok. Refactoring a bit to allow this later is trivial, if need be. Looking into this caught a bug in the original code. The "leftover value" code has to handle the case where the input value was 0. Otherwise, gdb will print nothing :) I only updated the DWARF reader since I know nothing about stabs; and, anyway, this is just a nicety. This version needs another doc review. I also added NEWS entries. Built and regtested on x86-64 F15. Tom b/gdb/ChangeLog: 2012-01-11 Tom Tromey <tromey@redhat.com> PR python/13281: * gdbtypes.h (TYPE_FLAG_ENUM): New macro. (struct main_type) <flag_flag_enum>: New field. * dwarf2read.c (process_enumeration_scope): Detect "flag" enums. * NEWS: Add entries. * c-valprint.c (c_val_print) <TYPE_CODE_ENUM>: Handle "flag" enums. * python/lib/gdb/printing.py (_EnumInstance): New class. (FlagEnumerationPrinter): Likewise. b/gdb/doc/ChangeLog: 2012-01-11 Tom Tromey <tromey@redhat.com> * gdb.texinfo (gdb.printing): Document FlagEnumerationPrinter. b/gdb/testsuite/ChangeLog: 2012-01-11 Tom Tromey <tromey@redhat.com> * gdb.base/printcmds.c (enum flag_enum): New. (three): New global. * gdb.base/printcmds.exp (test_print_enums): Add test for flag enum printing. * gdb.python/py-pp-maint.py (build_pretty_printer): Instantiate FlagEnumerationPrinter. * gdb.python/py-pp-maint.exp: Add tests for FlagEnumerationPrinter. * gdb.python/py-pp-maint.c (enum flag_enum): New. (fval): New global. diff --git a/gdb/NEWS b/gdb/NEWS index a9a7859..8119cf0 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -9,6 +9,18 @@ * The binary "gdbtui" can no longer be built or installed. Use "gdb -tui" instead. +* GDB will now print "flag" enums specially. A flag enum is one where + all the enumerator values have no bits in common when pairwise + "and"ed. When printing a value whose type is a flag enum, GDB will + show all the constants, e.g., for enum E { ONE = 1, TWO = 2}: + (gdb) print (enum E) 3 + $1 = [ONE | TWO] + +* Python scripting + + ** A new class, gdb.printing.FlagEnumerationPrinter, can be used to + apply "flag enum"-style pretty-printing to any enum. + *** Changes in GDB 7.4 * GDB now handles ambiguous linespecs more consistently; the existing diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index 9949015..1d44e90 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -458,7 +458,38 @@ c_val_print (struct type *type, const gdb_byte *valaddr, } else { - print_longest (stream, 'd', 0, val); + if (TYPE_FLAG_ENUM (type)) + { + int first = 1; + + fputs_filtered ("[", stream); + for (i = 0; i < len; ++i) + { + QUIT; + + if ((val & TYPE_FIELD_BITPOS (type, i)) != 0) + { + if (!first) + fputs_filtered (" | ", stream); + first = 0; + + val &= ~ TYPE_FIELD_BITPOS (type, i); + fputs_filtered (TYPE_FIELD_NAME (type, i), stream); + } + } + + if (first || val != 0) + { + if (!first) + fputs_filtered (" | ", stream); + fputs_filtered ("unknown: ", stream); + print_longest (stream, 'd', 0, val); + } + + fputs_filtered ("]", stream); + } + else + print_longest (stream, 'd', 0, val); } break; diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 4a8ff7b..de2e390 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -24720,6 +24720,13 @@ Utility class for handling multiple printers, all recognized via regular expressions. @xref{Writing a Pretty-Printer}, for an example. +@item FlagEnumerationPrinter (@var{name}) +A pretty-printer which handles printing of @code{enum} values. Unlike +@value{GDBN}'s built-in @code{enum} printing, this printer attempts to +work properly when there is some overlap between the enumeration +constants. @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/dwarf2read.c b/gdb/dwarf2read.c index 42dbac3..afb4337 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -7913,6 +7913,8 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) int num_fields = 0; int unsigned_enum = 1; char *name; + int flag_enum = 1; + ULONGEST mask = 0; child_die = die->child; while (child_die && child_die->tag) @@ -7928,7 +7930,14 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) { sym = new_symbol (child_die, this_type, cu); if (SYMBOL_VALUE (sym) < 0) - unsigned_enum = 0; + { + unsigned_enum = 0; + flag_enum = 0; + } + else if ((mask & SYMBOL_VALUE (sym)) != 0) + flag_enum = 0; + else + mask |= SYMBOL_VALUE (sym); if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0) { @@ -7961,6 +7970,8 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) } if (unsigned_enum) TYPE_UNSIGNED (this_type) = 1; + if (flag_enum) + TYPE_FLAG_ENUM (this_type) = 1; } /* If we are reading an enum from a .debug_types unit, and the enum diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index ddad0dc..f152945 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -290,6 +290,12 @@ enum type_instance_flag_value #define TYPE_DECLARED_CLASS(t) (TYPE_MAIN_TYPE (t)->flag_declared_class) +/* True if this type is a "flag" enum. A flag enum is one where all + the values are pairwise disjoint when "and"ed together. This + affects how enum values are printed. */ + +#define TYPE_FLAG_ENUM(t) (TYPE_MAIN_TYPE (t)->flag_flag_enum) + /* Constant type. If this is set, the corresponding type has a const modifier. */ @@ -399,6 +405,9 @@ struct main_type /* True if this type was declared with "class" rather than "struct". */ unsigned int flag_declared_class : 1; + /* True if this is an enum type with disjoint values. This affects + how the enum is printed. */ + unsigned int flag_flag_enum : 1; /* A discriminant telling us which field of the type_specific union is being used for this type, if any. */ diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py index 98cfd27..0f399d0 100644 --- a/gdb/python/lib/gdb/printing.py +++ b/gdb/python/lib/gdb/printing.py @@ -206,3 +206,53 @@ 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) + any_found = False + for (e_name, e_value) in self.enumerators: + if v & e_value != 0: + flag_list.append(e_name) + v = v & ~e_value + any_found = True + if not any_found or v != 0: + # Leftover value. + flag_list.append('<unknown: 0x%x>' % v) + return "0x%x [%s]" % (self.val, " | ".join(flag_list)) + +class FlagEnumerationPrinter(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. This printer is most useful when an enum is flag-like, + but has some overlap. GDB's built-in printing will not handle + this case, but this printer will attempt to.""" + + def __init__(self, enum_type): + super(FlagEnumerationPrinter, 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)) + # Sorting the enumerators by value usually does the right + # thing. + self.enumerators.sort(key = lambda x: x.bitpos) + + if self.enabled: + return _EnumInstance(self.enumerators, val) + else: + return None diff --git a/gdb/testsuite/gdb.base/printcmds.c b/gdb/testsuite/gdb.base/printcmds.c index d37dfbd..743734b 100644 --- a/gdb/testsuite/gdb.base/printcmds.c +++ b/gdb/testsuite/gdb.base/printcmds.c @@ -96,6 +96,10 @@ enum some_volatile_enum { enumvolval1, enumvolval2 }; name. See PR11827. */ volatile enum some_volatile_enum some_volatile_enum = enumvolval1; +enum flag_enum { ONE = 1, TWO = 2 }; + +enum flag_enum three = ONE | TWO; + /* A structure with an embedded array at an offset > 0. The array has all elements with the same repeating value, which must not be the same as the value of the preceding fields in the structure for the diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp index d647ca8..36d3af6 100644 --- a/gdb/testsuite/gdb.base/printcmds.exp +++ b/gdb/testsuite/gdb.base/printcmds.exp @@ -701,6 +701,8 @@ proc test_print_array_constants {} { proc test_print_enums {} { # Regression test for PR11827. gdb_test "print some_volatile_enum" "enumvolval1" + + gdb_test "print three" " = \\\[ONE \\| TWO\\\]" } proc test_printf {} { diff --git a/gdb/testsuite/gdb.python/py-pp-maint.c b/gdb/testsuite/gdb.python/py-pp-maint.c index f65e5f7..e91193a 100644 --- a/gdb/testsuite/gdb.python/py-pp-maint.c +++ b/gdb/testsuite/gdb.python/py-pp-maint.c @@ -17,6 +17,16 @@ #include <string.h> +enum flag_enum + { + FLAG_1 = 1, + FLAG_2 = 2, + FLAG_3 = 4, + ALL = FLAG_1 | FLAG_2 | FLAG_3 + }; + +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 1a2b213..5f591fb 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 c988f88..1677371 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.FlagEnumerationPrinter('enum flag_enum')) + return pp ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-11 16:46 ` Tom Tromey @ 2012-01-11 21:03 ` Jan Kratochvil 2012-01-11 21:25 ` Tom Tromey 0 siblings, 1 reply; 13+ messages in thread From: Jan Kratochvil @ 2012-01-11 21:03 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches Hi Tom, On Wed, 11 Jan 2012 17:45:16 +0100, Tom Tromey wrote: > Tom> I think the C code has to be a bit more careful because it > Tom> cannot readily be turned off. > Tom> > Tom> One idea is to have both. > > Jan> I agree. > > Here's a new patch. Let me know what you think. That's great now, thanks. FYI not reviewed the Python part. > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -9,6 +9,18 @@ > * The binary "gdbtui" can no longer be built or installed. > Use "gdb -tui" instead. > > +* GDB will now print "flag" enums specially. A flag enum is one where > + all the enumerator values have no bits in common when pairwise > + "and"ed. When printing a value whose type is a flag enum, GDB will > + show all the constants, e.g., for enum E { ONE = 1, TWO = 2}: > + (gdb) print (enum E) 3 > + $1 = [ONE | TWO] I do not much understand - why not to make it C syntax compliant? $1 = (ONE | TWO) > + > +* Python scripting > + > + ** A new class, gdb.printing.FlagEnumerationPrinter, can be used to > + apply "flag enum"-style pretty-printing to any enum. > + > *** Changes in GDB 7.4 > > * GDB now handles ambiguous linespecs more consistently; the existing > diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c > index 9949015..1d44e90 100644 > --- a/gdb/c-valprint.c > +++ b/gdb/c-valprint.c > @@ -458,7 +458,38 @@ c_val_print (struct type *type, const gdb_byte *valaddr, > } > else > { > - print_longest (stream, 'd', 0, val); > + if (TYPE_FLAG_ENUM (type)) Some comment here what this new block does, please. This "else if" can be indented left - one needless block/indentation here. > + { > + int first = 1; > + > + fputs_filtered ("[", stream); > + for (i = 0; i < len; ++i) > + { > + QUIT; > + > + if ((val & TYPE_FIELD_BITPOS (type, i)) != 0) > + { > + if (!first) > + fputs_filtered (" | ", stream); > + first = 0; > + > + val &= ~ TYPE_FIELD_BITPOS (type, i); ^ Extra space, not GDB coding style compliant. > + fputs_filtered (TYPE_FIELD_NAME (type, i), stream); > + } > + } > + > + if (first || val != 0) > + { > + if (!first) > + fputs_filtered (" | ", stream); > + fputs_filtered ("unknown: ", stream); > + print_longest (stream, 'd', 0, val); > + } > + > + fputs_filtered ("]", stream); > + } > + else > + print_longest (stream, 'd', 0, val); > } > break; > [...] > diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h > index ddad0dc..f152945 100644 > --- a/gdb/gdbtypes.h > +++ b/gdb/gdbtypes.h > @@ -290,6 +290,12 @@ enum type_instance_flag_value > > #define TYPE_DECLARED_CLASS(t) (TYPE_MAIN_TYPE (t)->flag_declared_class) > > +/* True if this type is a "flag" enum. A flag enum is one where all > + the values are pairwise disjoint when "and"ed together. This > + affects how enum values are printed. */ > + > +#define TYPE_FLAG_ENUM(t) (TYPE_MAIN_TYPE (t)->flag_flag_enum) > + > /* Constant type. If this is set, the corresponding type has a > const modifier. */ > > @@ -399,6 +405,9 @@ struct main_type > /* True if this type was declared with "class" rather than > "struct". */ > unsigned int flag_declared_class : 1; Empty line (OK, flag_declared_class is also wrong wrt this). > + /* True if this is an enum type with disjoint values. This affects > + how the enum is printed. */ > + unsigned int flag_flag_enum : 1; > > /* A discriminant telling us which field of the type_specific union > is being used for this type, if any. */ [...] > --- a/gdb/testsuite/gdb.python/py-pp-maint.exp > +++ b/gdb/testsuite/gdb.python/py-pp-maint.exp [...] > @@ -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" > + > + > + 3 extra empty lines. Thanks, Jan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-11 21:03 ` Jan Kratochvil @ 2012-01-11 21:25 ` Tom Tromey 2012-01-16 18:44 ` Tom Tromey 0 siblings, 1 reply; 13+ messages in thread From: Tom Tromey @ 2012-01-11 21:25 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches Jan> That's great now, thanks. FYI not reviewed the Python part. Thanks. Jan> I do not much understand - why not to make it C syntax compliant? Jan> $1 = (ONE | TWO) No good reason, just took it from the Python code. This version should address all your comments. Tom b/gdb/ChangeLog: 2012-01-11 Tom Tromey <tromey@redhat.com> PR python/13281: * gdbtypes.h (TYPE_FLAG_ENUM): New macro. (struct main_type) <flag_flag_enum>: New field. * dwarf2read.c (process_enumeration_scope): Detect "flag" enums. * NEWS: Add entries. * c-valprint.c (c_val_print) <TYPE_CODE_ENUM>: Handle "flag" enums. * python/lib/gdb/printing.py (_EnumInstance): New class. (FlagEnumerationPrinter): Likewise. b/gdb/doc/ChangeLog: 2012-01-11 Tom Tromey <tromey@redhat.com> * gdb.texinfo (gdb.printing): Document FlagEnumerationPrinter. b/gdb/testsuite/ChangeLog: 2012-01-11 Tom Tromey <tromey@redhat.com> * gdb.base/printcmds.c (enum flag_enum): New. (three): New global. * gdb.base/printcmds.exp (test_print_enums): Add test for flag enum printing. * gdb.python/py-pp-maint.py (build_pretty_printer): Instantiate FlagEnumerationPrinter. * gdb.python/py-pp-maint.exp: Add tests for FlagEnumerationPrinter. * gdb.python/py-pp-maint.c (enum flag_enum): New. (fval): New global. diff --git a/gdb/NEWS b/gdb/NEWS index a9a7859..571fd5e 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -9,6 +9,18 @@ * The binary "gdbtui" can no longer be built or installed. Use "gdb -tui" instead. +* GDB will now print "flag" enums specially. A flag enum is one where + all the enumerator values have no bits in common when pairwise + "and"ed. When printing a value whose type is a flag enum, GDB will + show all the constants, e.g., for enum E { ONE = 1, TWO = 2}: + (gdb) print (enum E) 3 + $1 = (ONE | TWO) + +* Python scripting + + ** A new class, gdb.printing.FlagEnumerationPrinter, can be used to + apply "flag enum"-style pretty-printing to any enum. + *** Changes in GDB 7.4 * GDB now handles ambiguous linespecs more consistently; the existing diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index 9949015..82551e9 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -456,10 +456,41 @@ c_val_print (struct type *type, const gdb_byte *valaddr, { fputs_filtered (TYPE_FIELD_NAME (type, i), stream); } - else + else if (TYPE_FLAG_ENUM (type)) { - print_longest (stream, 'd', 0, val); + int first = 1; + + /* We have a "flag" enum, so we try to decompose it into + pieces as appropriate. A flag enum has disjoint + constants by definition. */ + fputs_filtered ("(", stream); + for (i = 0; i < len; ++i) + { + QUIT; + + if ((val & TYPE_FIELD_BITPOS (type, i)) != 0) + { + if (!first) + fputs_filtered (" | ", stream); + first = 0; + + val &= ~TYPE_FIELD_BITPOS (type, i); + fputs_filtered (TYPE_FIELD_NAME (type, i), stream); + } + } + + if (first || val != 0) + { + if (!first) + fputs_filtered (" | ", stream); + fputs_filtered ("unknown: ", stream); + print_longest (stream, 'd', 0, val); + } + + fputs_filtered (")", stream); } + else + print_longest (stream, 'd', 0, val); break; case TYPE_CODE_FLAGS: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 4a8ff7b..de2e390 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -24720,6 +24720,13 @@ Utility class for handling multiple printers, all recognized via regular expressions. @xref{Writing a Pretty-Printer}, for an example. +@item FlagEnumerationPrinter (@var{name}) +A pretty-printer which handles printing of @code{enum} values. Unlike +@value{GDBN}'s built-in @code{enum} printing, this printer attempts to +work properly when there is some overlap between the enumeration +constants. @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/dwarf2read.c b/gdb/dwarf2read.c index 42dbac3..afb4337 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -7913,6 +7913,8 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) int num_fields = 0; int unsigned_enum = 1; char *name; + int flag_enum = 1; + ULONGEST mask = 0; child_die = die->child; while (child_die && child_die->tag) @@ -7928,7 +7930,14 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) { sym = new_symbol (child_die, this_type, cu); if (SYMBOL_VALUE (sym) < 0) - unsigned_enum = 0; + { + unsigned_enum = 0; + flag_enum = 0; + } + else if ((mask & SYMBOL_VALUE (sym)) != 0) + flag_enum = 0; + else + mask |= SYMBOL_VALUE (sym); if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0) { @@ -7961,6 +7970,8 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) } if (unsigned_enum) TYPE_UNSIGNED (this_type) = 1; + if (flag_enum) + TYPE_FLAG_ENUM (this_type) = 1; } /* If we are reading an enum from a .debug_types unit, and the enum diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index ddad0dc..2070f00 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -290,6 +290,12 @@ enum type_instance_flag_value #define TYPE_DECLARED_CLASS(t) (TYPE_MAIN_TYPE (t)->flag_declared_class) +/* True if this type is a "flag" enum. A flag enum is one where all + the values are pairwise disjoint when "and"ed together. This + affects how enum values are printed. */ + +#define TYPE_FLAG_ENUM(t) (TYPE_MAIN_TYPE (t)->flag_flag_enum) + /* Constant type. If this is set, the corresponding type has a const modifier. */ @@ -400,6 +406,11 @@ struct main_type "struct". */ unsigned int flag_declared_class : 1; + /* True if this is an enum type with disjoint values. This affects + how the enum is printed. */ + + unsigned int flag_flag_enum : 1; + /* A discriminant telling us which field of the type_specific union is being used for this type, if any. */ ENUM_BITFIELD(type_specific_kind) type_specific_field : 3; diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py index 98cfd27..0f399d0 100644 --- a/gdb/python/lib/gdb/printing.py +++ b/gdb/python/lib/gdb/printing.py @@ -206,3 +206,53 @@ 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) + any_found = False + for (e_name, e_value) in self.enumerators: + if v & e_value != 0: + flag_list.append(e_name) + v = v & ~e_value + any_found = True + if not any_found or v != 0: + # Leftover value. + flag_list.append('<unknown: 0x%x>' % v) + return "0x%x [%s]" % (self.val, " | ".join(flag_list)) + +class FlagEnumerationPrinter(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. This printer is most useful when an enum is flag-like, + but has some overlap. GDB's built-in printing will not handle + this case, but this printer will attempt to.""" + + def __init__(self, enum_type): + super(FlagEnumerationPrinter, 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)) + # Sorting the enumerators by value usually does the right + # thing. + self.enumerators.sort(key = lambda x: x.bitpos) + + if self.enabled: + return _EnumInstance(self.enumerators, val) + else: + return None diff --git a/gdb/testsuite/gdb.base/printcmds.c b/gdb/testsuite/gdb.base/printcmds.c index d37dfbd..743734b 100644 --- a/gdb/testsuite/gdb.base/printcmds.c +++ b/gdb/testsuite/gdb.base/printcmds.c @@ -96,6 +96,10 @@ enum some_volatile_enum { enumvolval1, enumvolval2 }; name. See PR11827. */ volatile enum some_volatile_enum some_volatile_enum = enumvolval1; +enum flag_enum { ONE = 1, TWO = 2 }; + +enum flag_enum three = ONE | TWO; + /* A structure with an embedded array at an offset > 0. The array has all elements with the same repeating value, which must not be the same as the value of the preceding fields in the structure for the diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp index d647ca8..a7fb4bd 100644 --- a/gdb/testsuite/gdb.base/printcmds.exp +++ b/gdb/testsuite/gdb.base/printcmds.exp @@ -701,6 +701,8 @@ proc test_print_array_constants {} { proc test_print_enums {} { # Regression test for PR11827. gdb_test "print some_volatile_enum" "enumvolval1" + + gdb_test "print three" " = \\\(ONE \\| TWO\\\)" } proc test_printf {} { diff --git a/gdb/testsuite/gdb.python/py-pp-maint.c b/gdb/testsuite/gdb.python/py-pp-maint.c index f65e5f7..e91193a 100644 --- a/gdb/testsuite/gdb.python/py-pp-maint.c +++ b/gdb/testsuite/gdb.python/py-pp-maint.c @@ -17,6 +17,16 @@ #include <string.h> +enum flag_enum + { + FLAG_1 = 1, + FLAG_2 = 2, + FLAG_3 = 4, + ALL = FLAG_1 | FLAG_2 | FLAG_3 + }; + +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 1a2b213..3d8e774 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,15 @@ 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 c988f88..1677371 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.FlagEnumerationPrinter('enum flag_enum')) + return pp ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-11 21:25 ` Tom Tromey @ 2012-01-16 18:44 ` Tom Tromey 2012-01-16 18:45 ` Eli Zaretskii 0 siblings, 1 reply; 13+ messages in thread From: Tom Tromey @ 2012-01-16 18:44 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches, Eli Zaretskii This updated version needs a doc review. I minorly changed the texi and I added a NEWS entry. Tom> * NEWS: Add entries. Tom> b/gdb/doc/ChangeLog: Tom> 2012-01-11 Tom Tromey <tromey@redhat.com> Tom> * gdb.texinfo (gdb.printing): Document FlagEnumerationPrinter. Tom ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: RFC: enum pretty-printing support 2012-01-16 18:44 ` Tom Tromey @ 2012-01-16 18:45 ` Eli Zaretskii 0 siblings, 0 replies; 13+ messages in thread From: Eli Zaretskii @ 2012-01-16 18:45 UTC (permalink / raw) To: Tom Tromey; +Cc: jan.kratochvil, gdb-patches > From: Tom Tromey <tromey@redhat.com> > Cc: gdb-patches@sourceware.org, Eli Zaretskii <eliz@elta.co.il> > Date: Mon, 16 Jan 2012 10:23:07 -0700 > > This updated version needs a doc review. > I minorly changed the texi and I added a NEWS entry. > > Tom> * NEWS: Add entries. > > Tom> b/gdb/doc/ChangeLog: > Tom> 2012-01-11 Tom Tromey <tromey@redhat.com> > > Tom> * gdb.texinfo (gdb.printing): Document FlagEnumerationPrinter. OK. ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2012-01-16 18:44 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-01-10 20:26 RFC: enum pretty-printing support Tom Tromey 2012-01-10 20:28 ` Pedro Alves 2012-01-11 16:45 ` Tom Tromey 2012-01-10 21:19 ` Eli Zaretskii 2012-01-10 21:23 ` Jan Kratochvil 2012-01-10 22:00 ` Tom Tromey 2012-01-10 22:19 ` Tom Tromey 2012-01-10 23:52 ` Jan Kratochvil 2012-01-11 16:46 ` Tom Tromey 2012-01-11 21:03 ` Jan Kratochvil 2012-01-11 21:25 ` Tom Tromey 2012-01-16 18:44 ` Tom Tromey 2012-01-16 18:45 ` Eli Zaretskii
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).