From d63c53cce2d137062e4f93a9ff410e684bc7bc1b Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 14 Mar 2011 20:29:23 +0000 Subject: [PATCH] printers.py (_use_gdb_pp): New global. * python/libstdcxx/v6/printers.py (_use_gdb_pp): New global. Try to import `gdb.printing' module. (UniquePointerPrinter.__init__): Add 'typename' argument. (StdSlistPrinter.__init__): Likewise. (StdSlistIteratorPrinter.__init__): Likewise. (StdVectorIteratorPrinter.__init__): Likewise. (StdRbtreeIteratorPrinter.__init__): Likewise. (StdDebugIteratorPrinter.__init__): Likewise. (StdDequeIteratorPrinter.__init__): Likewise. (StdStringPrinter.__init__): Likewise. (RxPrinter, Printer): New class. (libstdcxx_printer): New global. (register_libstdcxx_printers): Rewrite. (build_libstdcxx_dictionary): Rewrite. (pretty_printers_dict): Remove. From-SVN: r170958 --- libstdc++-v3/ChangeLog | 18 ++ libstdc++-v3/python/libstdcxx/v6/printers.py | 267 ++++++++++++------- 2 files changed, 187 insertions(+), 98 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ef93431bf09..7e8d6da9c3a 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,21 @@ +2011-03-14 Tom Tromey + + * python/libstdcxx/v6/printers.py (_use_gdb_pp): New global. + Try to import `gdb.printing' module. + (UniquePointerPrinter.__init__): Add 'typename' argument. + (StdSlistPrinter.__init__): Likewise. + (StdSlistIteratorPrinter.__init__): Likewise. + (StdVectorIteratorPrinter.__init__): Likewise. + (StdRbtreeIteratorPrinter.__init__): Likewise. + (StdDebugIteratorPrinter.__init__): Likewise. + (StdDequeIteratorPrinter.__init__): Likewise. + (StdStringPrinter.__init__): Likewise. + (RxPrinter, Printer): New class. + (libstdcxx_printer): New global. + (register_libstdcxx_printers): Rewrite. + (build_libstdcxx_dictionary): Rewrite. + (pretty_printers_dict): Remove. + 2011-03-14 Andrey Zholos PR libstdc++/48114 diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index fb999bf5257..241ae042fe6 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -1,6 +1,6 @@ # Pretty-printers for libstc++. -# Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. +# Copyright (C) 2008, 2009, 2010, 2011 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 @@ -19,6 +19,13 @@ import gdb import itertools import re +# Try to use the new-style pretty-printing if available. +_use_gdb_pp = True +try: + import gdb.printing +except ImportError: + _use_gdb_pp = False + class StdPointerPrinter: "Print a smart pointer of some kind" @@ -36,7 +43,7 @@ class StdPointerPrinter: class UniquePointerPrinter: "Print a unique_ptr" - def __init__ (self, val): + def __init__ (self, typename, val): self.val = val def to_string (self): @@ -125,7 +132,7 @@ class StdSlistPrinter: self.count = self.count + 1 return ('[%d]' % count, elt['_M_data']) - def __init__(self, val): + def __init__(self, typename, val): self.val = val def children(self): @@ -141,7 +148,7 @@ class StdSlistPrinter: class StdSlistIteratorPrinter: "Print __gnu_cxx::slist::iterator" - def __init__(self, val): + def __init__(self, typename, val): self.val = val def to_string(self): @@ -228,7 +235,7 @@ class StdVectorPrinter: class StdVectorIteratorPrinter: "Print std::vector::iterator" - def __init__(self, val): + def __init__(self, typename, val): self.val = val def to_string(self): @@ -351,7 +358,7 @@ class RbtreeIterator: class StdRbtreeIteratorPrinter: "Print std::map::iterator" - def __init__ (self, val): + def __init__ (self, typename, val): self.val = val def to_string (self): @@ -363,7 +370,7 @@ class StdRbtreeIteratorPrinter: class StdDebugIteratorPrinter: "Print a debug enabled version of an iterator" - def __init__ (self, val): + def __init__ (self, typename, val): self.val = val # Just strip away the encapsulating __gnu_debug::_Safe_iterator @@ -557,7 +564,7 @@ class StdDequePrinter: class StdDequeIteratorPrinter: "Print std::deque::iterator" - def __init__(self, val): + def __init__(self, typename, val): self.val = val def to_string(self): @@ -566,7 +573,7 @@ class StdDequeIteratorPrinter: class StdStringPrinter: "Print a std::basic_string of some kind" - def __init__(self, val): + def __init__(self, typename, val): self.val = val def to_string(self): @@ -678,125 +685,189 @@ class Tr1UnorderedMapPrinter: def display_hint (self): return 'map' -def register_libstdcxx_printers (obj): - "Register libstdc++ pretty-printers with objfile Obj." +# A "regular expression" printer which conforms to the +# "SubPrettyPrinter" protocol from gdb.printing. +class RxPrinter(object): + def __init__(self, name, function): + super(RxPrinter, self).__init__() + self.name = name + self.function = function + self.enabled = True + + def invoke(self, value): + if not self.enabled: + return None + return self.function(self.name, value) + +# A pretty-printer that conforms to the "PrettyPrinter" protocol from +# gdb.printing. It can also be used directly as an old-style printer. +class Printer(object): + def __init__(self, name): + super(Printer, self).__init__() + self.name = name + self.subprinters = [] + self.lookup = {} + self.enabled = True + self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)<.*>$') + + def add(self, name, function): + # A small sanity check. + # FIXME + if not self.compiled_rx.match(name + '<>'): + raise ValueError, 'libstdc++ programming error: "%s" does not match' % name + printer = RxPrinter(name, function) + self.subprinters.append(printer) + self.lookup[name] = printer - if obj == None: - obj = gdb + @staticmethod + def get_basic_type(type): + # If it points to a reference, get the reference. + if type.code == gdb.TYPE_CODE_REF: + type = type.target () - obj.pretty_printers.append (lookup_function) + # Get the unqualified type, stripped of typedefs. + type = type.unqualified ().strip_typedefs () -def lookup_function (val): - "Look-up and return a pretty-printer that can print val." + return type.tag - # Get the type. - type = val.type + def __call__(self, val): + typename = self.get_basic_type(val.type) + if not typename: + return None - # If it points to a reference, get the reference. - if type.code == gdb.TYPE_CODE_REF: - type = type.target () + # All the types we match are template types, so we can use a + # dictionary. + match = self.compiled_rx.match(typename) + if not match: + return None - # Get the unqualified type, stripped of typedefs. - type = type.unqualified ().strip_typedefs () + basename = match.group(1) + if basename in self.lookup: + return self.lookup[basename].invoke(val) - # Get the type name. - typename = type.tag - if typename == None: + # Cannot find a pretty printer. Return None. return None - # Iterate over local dictionary of types to determine - # if a printer is registered for that type. Return an - # instantiation of the printer if found. - for function in pretty_printers_dict: - if function.search (typename): - return pretty_printers_dict[function] (val) - - # Cannot find a pretty printer. Return None. - return None +libstdcxx_printer = None + +def register_libstdcxx_printers (obj): + "Register libstdc++ pretty-printers with objfile Obj." + + global _use_gdb_pp + global libstdcxx_printer + + if _use_gdb_pp: + gdb.printing.register_pretty_printer(obj, libstdcxx_printer) + else: + if obj is None: + obj = gdb + obj.pretty_printers.append(libstdcxx_printer) def build_libstdcxx_dictionary (): + global libstdcxx_printer + + libstdcxx_printer = Printer("libstdc++-v6") + # libstdc++ objects requiring pretty-printing. # In order from: # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html - pretty_printers_dict[re.compile('^std::basic_string<.*>$')] = lambda val: StdStringPrinter(val) - pretty_printers_dict[re.compile('^std::bitset<.*>$')] = lambda val: StdBitsetPrinter("std::bitset", val) - pretty_printers_dict[re.compile('^std::deque<.*>$')] = lambda val: StdDequePrinter("std::deque", val) - pretty_printers_dict[re.compile('^std::list<.*>$')] = lambda val: StdListPrinter("std::list", val) - pretty_printers_dict[re.compile('^std::map<.*>$')] = lambda val: StdMapPrinter("std::map", val) - pretty_printers_dict[re.compile('^std::multimap<.*>$')] = lambda val: StdMapPrinter("std::multimap", val) - pretty_printers_dict[re.compile('^std::multiset<.*>$')] = lambda val: StdSetPrinter("std::multiset", val) - pretty_printers_dict[re.compile('^std::priority_queue<.*>$')] = lambda val: StdStackOrQueuePrinter("std::priority_queue", val) - pretty_printers_dict[re.compile('^std::queue<.*>$')] = lambda val: StdStackOrQueuePrinter("std::queue", val) - pretty_printers_dict[re.compile('^std::tuple<.*>$')] = lambda val: StdTuplePrinter("std::tuple", val) - pretty_printers_dict[re.compile('^std::set<.*>$')] = lambda val: StdSetPrinter("std::set", val) - pretty_printers_dict[re.compile('^std::stack<.*>$')] = lambda val: StdStackOrQueuePrinter("std::stack", val) - pretty_printers_dict[re.compile('^std::unique_ptr<.*>$')] = UniquePointerPrinter - pretty_printers_dict[re.compile('^std::vector<.*>$')] = lambda val: StdVectorPrinter("std::vector", val) + libstdcxx_printer.add('std::basic_string', StdStringPrinter) + libstdcxx_printer.add('std::bitset', StdBitsetPrinter) + libstdcxx_printer.add('std::deque', StdDequePrinter) + libstdcxx_printer.add('std::list', StdListPrinter) + libstdcxx_printer.add('std::map', StdMapPrinter) + libstdcxx_printer.add('std::multimap', StdMapPrinter) + libstdcxx_printer.add('std::multiset', StdSetPrinter) + libstdcxx_printer.add('std::priority_queue', StdStackOrQueuePrinter) + libstdcxx_printer.add('std::queue', StdStackOrQueuePrinter) + libstdcxx_printer.add('std::tuple', StdTuplePrinter) + libstdcxx_printer.add('std::set', StdSetPrinter) + libstdcxx_printer.add('std::stack', StdStackOrQueuePrinter) + libstdcxx_printer.add('std::unique_ptr', UniquePointerPrinter) + libstdcxx_printer.add('std::vector', StdVectorPrinter) # vector # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG. - pretty_printers_dict[re.compile('^std::__debug::bitset<.*>$')] = lambda val: StdBitsetPrinter("std::__debug::bitset", val) - pretty_printers_dict[re.compile('^std::__debug::deque<.*>$')] = lambda val: StdDequePrinter("std::__debug::deque", val) - pretty_printers_dict[re.compile('^std::__debug::list<.*>$')] = lambda val: StdListPrinter("std::__debug::list", val) - pretty_printers_dict[re.compile('^std::__debug::map<.*>$')] = lambda val: StdMapPrinter("std::__debug::map", val) - pretty_printers_dict[re.compile('^std::__debug::multimap<.*>$')] = lambda val: StdMapPrinter("std::__debug::multimap", val) - pretty_printers_dict[re.compile('^std::__debug::multiset<.*>$')] = lambda val: StdSetPrinter("std::__debug::multiset", val) - pretty_printers_dict[re.compile('^std::__debug::priority_queue<.*>$')] = lambda val: StdStackOrQueuePrinter("std::__debug::priority_queue", val) - pretty_printers_dict[re.compile('^std::__debug::queue<.*>$')] = lambda val: StdStackOrQueuePrinter("std::__debug::queue", val) - pretty_printers_dict[re.compile('^std::__debug::set<.*>$')] = lambda val: StdSetPrinter("std::__debug::set", val) - pretty_printers_dict[re.compile('^std::__debug::stack<.*>$')] = lambda val: StdStackOrQueuePrinter("std::__debug::stack", val) - pretty_printers_dict[re.compile('^std::__debug::unique_ptr<.*>$')] = UniquePointerPrinter - pretty_printers_dict[re.compile('^std::__debug::vector<.*>$')] = lambda val: StdVectorPrinter("std::__debug::vector", val) + libstdcxx_printer.add('std::__debug::bitset', StdBitsetPrinter) + libstdcxx_printer.add('std::__debug::deque', StdDequePrinter) + libstdcxx_printer.add('std::__debug::list', StdListPrinter) + libstdcxx_printer.add('std::__debug::map', StdMapPrinter) + libstdcxx_printer.add('std::__debug::multimap', StdMapPrinter) + libstdcxx_printer.add('std::__debug::multiset', StdSetPrinter) + libstdcxx_printer.add('std::__debug::priority_queue', + StdStackOrQueuePrinter) + libstdcxx_printer.add('std::__debug::queue', StdStackOrQueuePrinter) + libstdcxx_printer.add('std::__debug::set', StdSetPrinter) + libstdcxx_printer.add('std::__debug::stack', StdStackOrQueuePrinter) + libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter) + libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter) # These are the TR1 and C++0x printers. # For array - the default GDB pretty-printer seems reasonable. - pretty_printers_dict[re.compile('^std::shared_ptr<.*>$')] = lambda val: StdPointerPrinter ('std::shared_ptr', val) - pretty_printers_dict[re.compile('^std::weak_ptr<.*>$')] = lambda val: StdPointerPrinter ('std::weak_ptr', val) - pretty_printers_dict[re.compile('^std::unordered_map<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::unordered_map', val) - pretty_printers_dict[re.compile('^std::unordered_set<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::unordered_set', val) - pretty_printers_dict[re.compile('^std::unordered_multimap<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::unordered_multimap', val) - pretty_printers_dict[re.compile('^std::unordered_multiset<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::unordered_multiset', val) - - pretty_printers_dict[re.compile('^std::tr1::shared_ptr<.*>$')] = lambda val: StdPointerPrinter ('std::tr1::shared_ptr', val) - pretty_printers_dict[re.compile('^std::tr1::weak_ptr<.*>$')] = lambda val: StdPointerPrinter ('std::tr1::weak_ptr', val) - pretty_printers_dict[re.compile('^std::tr1::unordered_map<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::tr1::unordered_map', val) - pretty_printers_dict[re.compile('^std::tr1::unordered_set<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::tr1::unordered_set', val) - pretty_printers_dict[re.compile('^std::tr1::unordered_multimap<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::tr1::unordered_multimap', val) - pretty_printers_dict[re.compile('^std::tr1::unordered_multiset<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::tr1::unordered_multiset', val) + libstdcxx_printer.add('std::shared_ptr', StdPointerPrinter) + libstdcxx_printer.add('std::weak_ptr', StdPointerPrinter) + libstdcxx_printer.add('std::unordered_map', Tr1UnorderedMapPrinter) + libstdcxx_printer.add('std::unordered_set', Tr1UnorderedSetPrinter) + libstdcxx_printer.add('std::unordered_multimap', Tr1UnorderedMapPrinter) + libstdcxx_printer.add('std::unordered_multiset', Tr1UnorderedSetPrinter) + + libstdcxx_printer.add('std::tr1::shared_ptr', StdPointerPrinter) + libstdcxx_printer.add('std::tr1::weak_ptr', StdPointerPrinter) + libstdcxx_printer.add('std::tr1::unordered_map', Tr1UnorderedMapPrinter) + libstdcxx_printer.add('std::tr1::unordered_set', Tr1UnorderedSetPrinter) + libstdcxx_printer.add('std::tr1::unordered_multimap', + Tr1UnorderedMapPrinter) + libstdcxx_printer.add('std::tr1::unordered_multiset', + Tr1UnorderedSetPrinter) # These are the C++0x printer registrations for -D_GLIBCXX_DEBUG cases. # The tr1 namespace printers do not seem to have any debug # equivalents, so do no register them. - pretty_printers_dict[re.compile('^std::__debug::unordered_map<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::__debug::unordered_map', val) - pretty_printers_dict[re.compile('^std::__debug::unordered_set<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::__debug::unordered_set', val) - pretty_printers_dict[re.compile('^std::__debug::unordered_multimap<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::__debug::unordered_multimap', val) - pretty_printers_dict[re.compile('^std::__debug::unordered_multiset<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::__debug:unordered_multiset', val) + libstdcxx_printer.add('std::__debug::unordered_map', + Tr1UnorderedMapPrinter) + libstdcxx_printer.add('std::__debug::unordered_set', + Tr1UnorderedSetPrinter) + libstdcxx_printer.add('std::__debug::unordered_multimap', + Tr1UnorderedMapPrinter) + libstdcxx_printer.add('std::__debug::unordered_multiset', + Tr1UnorderedSetPrinter) # Extensions. - pretty_printers_dict[re.compile('^__gnu_cxx::slist<.*>$')] = StdSlistPrinter + libstdcxx_printer.add('__gnu_cxx::slist', StdSlistPrinter) if True: # These shouldn't be necessary, if GDB "print *i" worked. # But it often doesn't, so here they are. - pretty_printers_dict[re.compile('^std::_List_iterator<.*>$')] = lambda val: StdListIteratorPrinter("std::_List_iterator",val) - pretty_printers_dict[re.compile('^std::_List_const_iterator<.*>$')] = lambda val: StdListIteratorPrinter("std::_List_const_iterator",val) - pretty_printers_dict[re.compile('^std::_Rb_tree_iterator<.*>$')] = lambda val: StdRbtreeIteratorPrinter(val) - pretty_printers_dict[re.compile('^std::_Rb_tree_const_iterator<.*>$')] = lambda val: StdRbtreeIteratorPrinter(val) - pretty_printers_dict[re.compile('^std::_Deque_iterator<.*>$')] = lambda val: StdDequeIteratorPrinter(val) - pretty_printers_dict[re.compile('^std::_Deque_const_iterator<.*>$')] = lambda val: StdDequeIteratorPrinter(val) - pretty_printers_dict[re.compile('^__gnu_cxx::__normal_iterator<.*>$')] = lambda val: StdVectorIteratorPrinter(val) - pretty_printers_dict[re.compile('^__gnu_cxx::_Slist_iterator<.*>$')] = lambda val: StdSlistIteratorPrinter(val) - - # Debug (compiled with -D_GLIBCXX_DEBUG) printer registrations. - # The Rb_tree debug iterator when unwrapped from the encapsulating __gnu_debug::_Safe_iterator - # does not have the __norm namespace. Just use the existing printer registration for that. - pretty_printers_dict[re.compile('^__gnu_debug::_Safe_iterator<.*>$')] = lambda val: StdDebugIteratorPrinter(val) - pretty_printers_dict[re.compile('^std::__norm::_List_iterator<.*>$')] = lambda val: StdListIteratorPrinter ("std::__norm::_List_iterator",val) - pretty_printers_dict[re.compile('^std::__norm::_List_const_iterator<.*>$')] = lambda val: StdListIteratorPrinter ("std::__norm::_List_const_iterator",val) - pretty_printers_dict[re.compile('^std::__norm::_Deque_const_iterator<.*>$')] = lambda val: StdDequeIteratorPrinter(val) - pretty_printers_dict[re.compile('^std::__norm::_Deque_iterator<.*>$')] = lambda val: StdDequeIteratorPrinter(val) - -pretty_printers_dict = {} + libstdcxx_printer.add('std::_List_iterator', StdListIteratorPrinter) + libstdcxx_printer.add('std::_List_const_iterator', + StdListIteratorPrinter) + libstdcxx_printer.add('std::_Rb_tree_iterator', + StdRbtreeIteratorPrinter) + libstdcxx_printer.add('std::_Rb_tree_const_iterator', + StdRbtreeIteratorPrinter) + libstdcxx_printer.add('std::_Deque_iterator', StdDequeIteratorPrinter) + libstdcxx_printer.add('std::_Deque_const_iterator', + StdDequeIteratorPrinter) + libstdcxx_printer.add('__gnu_cxx::__normal_iterator', + StdVectorIteratorPrinter) + libstdcxx_printer.add('__gnu_cxx::_Slist_iterator', + StdSlistIteratorPrinter) + + # Debug (compiled with -D_GLIBCXX_DEBUG) printer + # registrations. The Rb_tree debug iterator when unwrapped + # from the encapsulating __gnu_debug::_Safe_iterator does not + # have the __norm namespace. Just use the existing printer + # registration for that. + libstdcxx_printer.add('__gnu_debug::_Safe_iterator', + StdDebugIteratorPrinter) + libstdcxx_printer.add('std::__norm::_List_iterator', + StdListIteratorPrinter) + libstdcxx_printer.add('std::__norm::_List_const_iterator', + StdListIteratorPrinter) + libstdcxx_printer.add('std::__norm::_Deque_const_iterator', + StdDequeIteratorPrinter) + libstdcxx_printer.add('std::__norm::_Deque_iterator', + StdDequeIteratorPrinter) build_libstdcxx_dictionary () -- 2.30.2