# 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
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"
class UniquePointerPrinter:
"Print a unique_ptr"
- def __init__ (self, val):
+ def __init__ (self, typename, val):
self.val = val
def to_string (self):
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):
class StdSlistIteratorPrinter:
"Print __gnu_cxx::slist::iterator"
- def __init__(self, val):
+ def __init__(self, typename, val):
self.val = val
def to_string(self):
class StdVectorIteratorPrinter:
"Print std::vector::iterator"
- def __init__(self, val):
+ def __init__(self, typename, val):
self.val = val
def to_string(self):
class StdRbtreeIteratorPrinter:
"Print std::map::iterator"
- def __init__ (self, val):
+ def __init__ (self, typename, val):
self.val = val
def to_string (self):
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
class StdDequeIteratorPrinter:
"Print std::deque::iterator"
- def __init__(self, val):
+ def __init__(self, typename, val):
self.val = val
def to_string(self):
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):
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<bool>
# 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 ()