OSDN Git Service

PR libstdc++/45403
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / python / libstdcxx / v6 / printers.py
index e2bb231..bf3689b 100644 (file)
@@ -1,6 +1,6 @@
 # Pretty-printers for libstc++.
 
-# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+# Copyright (C) 2008, 2009, 2010 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
@@ -64,28 +64,44 @@ class StdListPrinter:
             self.count = self.count + 1
             return ('[%d]' % count, elt['_M_data'])
 
-    def __init__(self, val):
+    def __init__(self, typename, val):
+        self.typename = typename
         self.val = val
 
     def children(self):
         itype = self.val.type.template_argument(0)
-        nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer()
+        # If the inferior program is compiled with -D_GLIBCXX_DEBUG
+        # some of the internal implementation details change.
+        if self.typename == "std::list":
+            nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer()
+        elif self.typename == "std::__debug::list":
+            nodetype = gdb.lookup_type('std::__norm::_List_node<%s>' % itype).pointer()
+        else:
+            raise ValueError, "Cannot cast list node for list printer."
         return self._iterator(nodetype, self.val['_M_impl']['_M_node'])
 
     def to_string(self):
         if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']:
-            return 'empty std::list'
-        return 'std::list'
+            return 'empty %s' % (self.typename)
+        return '%s' % (self.typename)
 
 class StdListIteratorPrinter:
     "Print std::list::iterator"
 
-    def __init__(self, val):
+    def __init__(self, typename, val):
         self.val = val
+        self.typename = typename
 
     def to_string(self):
         itype = self.val.type.template_argument(0)
-        nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer()
+        # If the inferior program is compiled with -D_GLIBCXX_DEBUG
+        # some of the internal implementation details change.
+        if self.typename == "std::_List_iterator" or self.typename == "std::_List_const_iterator":
+            nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer()
+        elif self.typename == "std::__norm::_List_iterator" or self.typename == "std::__norm::_List_const_iterator":
+            nodetype = gdb.lookup_type('std::__norm::_List_node<%s>' % itype).pointer()
+        else:
+            raise ValueError, "Cannot cast list node for list iterator printer."
         return self.val['_M_node'].cast(nodetype).dereference()['_M_data']
 
 class StdSlistPrinter:
@@ -137,36 +153,71 @@ class StdVectorPrinter:
     "Print a std::vector"
 
     class _iterator:
-        def __init__ (self, start, finish):
-            self.item = start
-            self.finish = finish
+        def __init__ (self, start, finish, bitvec):
+            self.bitvec = bitvec
+            if bitvec:
+                self.item   = start['_M_p']
+                self.so     = start['_M_offset']
+                self.finish = finish['_M_p']
+                self.fo     = finish['_M_offset']
+                itype = self.item.dereference().type
+                self.isize = 8 * itype.sizeof
+            else:
+                self.item = start
+                self.finish = finish
             self.count = 0
 
         def __iter__(self):
             return self
 
         def next(self):
-            if self.item == self.finish:
-                raise StopIteration
             count = self.count
             self.count = self.count + 1
-            elt = self.item.dereference()
-            self.item = self.item + 1
-            return ('[%d]' % count, elt)
+            if self.bitvec:
+                if self.item == self.finish and self.so >= self.fo:
+                    raise StopIteration
+                elt = self.item.dereference()
+                obit = 1 if elt & (1 << self.so) else 0
+                self.so = self.so + 1
+                if self.so >= self.isize:
+                    self.item = self.item + 1
+                    self.so = 0
+                return ('[%d]' % count, obit)
+            else:
+                if self.item == self.finish:
+                    raise StopIteration
+                elt = self.item.dereference()
+                self.item = self.item + 1
+                return ('[%d]' % count, elt)
 
-    def __init__(self, val):
+    def __init__(self, typename, val):
+        self.typename = typename
         self.val = val
+        self.is_bool = val.type.template_argument(0).code  == gdb.TYPE_CODE_BOOL
 
     def children(self):
         return self._iterator(self.val['_M_impl']['_M_start'],
-                              self.val['_M_impl']['_M_finish'])
+                              self.val['_M_impl']['_M_finish'],
+                              self.is_bool)
 
     def to_string(self):
         start = self.val['_M_impl']['_M_start']
         finish = self.val['_M_impl']['_M_finish']
         end = self.val['_M_impl']['_M_end_of_storage']
-        return ('std::vector of length %d, capacity %d'
-                % (int (finish - start), int (end - start)))
+        if self.is_bool:
+            start = self.val['_M_impl']['_M_start']['_M_p']
+            so    = self.val['_M_impl']['_M_start']['_M_offset']
+            finish = self.val['_M_impl']['_M_finish']['_M_p']
+            fo     = self.val['_M_impl']['_M_finish']['_M_offset']
+            itype = start.dereference().type
+            bl = 8 * itype.sizeof
+            length   = (bl - so) + bl * ((finish - start) - 1) + fo
+            capacity = bl * (end - start)
+            return ('%s<bool> of length %d, capacity %d'
+                    % (self.typename, int (length), int (capacity)))
+        else:
+            return ('%s of length %d, capacity %d'
+                    % (self.typename, int (finish - start), int (end - start)))
 
     def display_hint(self):
         return 'array'
@@ -180,6 +231,64 @@ class StdVectorIteratorPrinter:
     def to_string(self):
         return self.val['_M_current'].dereference()
 
+class StdTuplePrinter:
+    "Print a std::tuple"
+
+    class _iterator:
+        def __init__ (self, head):
+            self.head = head
+
+            # Set the base class as the initial head of the
+            # tuple.
+            nodes = self.head.type.fields ()
+            if len (nodes) != 1:
+                raise ValueError, "Top of tuple tree does not consist of a single node."
+
+            # Set the actual head to the first pair.
+            self.head  = self.head.cast (nodes[0].type)
+            self.count = 0
+
+        def __iter__ (self):
+            return self
+
+        def next (self):
+            nodes = self.head.type.fields ()
+            # Check for further recursions in the inheritance tree.
+            if len (nodes) == 0:
+                raise StopIteration
+            # Check that this iteration has an expected structure.
+            if len (nodes) != 2:
+                raise ValueError, "Cannot parse more than 2 nodes in a tuple tree."
+
+            # - Left node is the next recursion parent.
+            # - Right node is the actual class contained in the tuple.
+
+            # Process right node.
+            impl = self.head.cast (nodes[1].type)
+
+            # Process left node and set it as head.
+            self.head  = self.head.cast (nodes[0].type)
+            self.count = self.count + 1
+
+            # Finally, check the implementation.  If it is
+            # wrapped in _M_head_impl return that, otherwise return
+            # the value "as is".
+            fields = impl.type.fields ()
+            if len (fields) < 1 or fields[0].name != "_M_head_impl":
+                return ('[%d]' % self.count, impl)
+            else:
+                return ('[%d]' % self.count, impl['_M_head_impl'])
+
+    def __init__ (self, typename, val):
+        self.typename = typename
+        self.val = val;
+
+    def children (self):
+        return self._iterator (self.val)
+
+    def to_string (self):
+        return '%s containing' % (self.typename)
+
 class StdStackOrQueuePrinter:
     "Print a std::stack or std::queue"
 
@@ -248,6 +357,17 @@ class StdRbtreeIteratorPrinter:
         nodetype = nodetype.pointer()
         return self.val.cast(nodetype).dereference()['_M_value_field']
 
+class StdDebugIteratorPrinter:
+    "Print a debug enabled version of an iterator"
+
+    def __init__ (self, val):
+        self.val = val
+
+    # Just strip away the encapsulating __gnu_debug::_Safe_iterator
+    # and return the wrapped iterator value.
+    def to_string (self):
+        itype = self.val.type.template_argument(0)
+        return self.val['_M_current'].cast(itype)
 
 class StdMapPrinter:
     "Print a std::map or std::multimap"
@@ -330,13 +450,14 @@ class StdSetPrinter:
 class StdBitsetPrinter:
     "Print a std::bitset"
 
-    def __init__(self, val):
+    def __init__(self, typename, val):
+        self.typename = typename
         self.val = val
 
     def to_string (self):
         # If template_argument handled values, we could print the
         # size.  Or we could use a regexp on the type.
-        return 'std::bitset'
+        return '%s' % (self.typename)
 
     def children (self):
         words = self.val['_M_w']
@@ -399,7 +520,8 @@ class StdDequePrinter:
 
             return result
 
-    def __init__(self, val):
+    def __init__(self, typename, val):
+        self.typename = typename
         self.val = val
         self.elttype = val.type.template_argument(0)
         size = self.elttype.sizeof
@@ -418,7 +540,7 @@ class StdDequePrinter:
 
         size = self.buffer_size * delta_n + delta_s + delta_e
 
-        return 'std::deque with %d elements' % long (size)
+        return '%s with %d elements' % (self.typename, long (size))
 
     def children(self):
         start = self.val['_M_impl']['_M_start']
@@ -441,18 +563,26 @@ class StdDequeIteratorPrinter:
 class StdStringPrinter:
     "Print a std::basic_string of some kind"
 
-    def __init__(self, encoding, val):
-        self.encoding = encoding
+    def __init__(self, val):
         self.val = val
 
     def to_string(self):
-        # Look up the target encoding as late as possible.
-        encoding = self.encoding
-        if encoding == 0:
-            encoding = gdb.parameter('target-charset')
-        elif encoding == 1:
-            encoding = gdb.parameter('target-wide-charset')
-        return self.val['_M_dataplus']['_M_p'].string(encoding)
+        # Make sure &string works, too.
+        type = self.val.type
+        if type.code == gdb.TYPE_CODE_REF:
+            type = type.target ()
+
+        # Calculate the length of the string so that to_string returns
+        # the string according to length, not according to first null
+        # encountered.
+        ptr = self.val ['_M_dataplus']['_M_p']
+        realtype = type.unqualified ().strip_typedefs ()
+        reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
+        header = ptr.cast(reptype) - 1
+        len = header.dereference ()['_M_length']
+        if hasattr(ptr, "lazy_string"):
+            return ptr.lazy_string (length = len)
+        return ptr.string (length = len)
 
     def display_hint (self):
         return 'string'
@@ -585,24 +715,36 @@ def build_libstdcxx_dictionary ():
     # 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<char(,.*)?>$')] = lambda val: StdStringPrinter(0, val)
-    pretty_printers_dict[re.compile('^std::basic_string<wchar_t(,.*)?>$')] = lambda val: StdStringPrinter(1, val)
-    pretty_printers_dict[re.compile('^std::basic_string<char16_t(,.*)?>$')] = lambda val: StdStringPrinter('UTF-16', val)
-    pretty_printers_dict[re.compile('^std::basic_string<char32_t(,.*)?>$')] = lambda val: StdStringPrinter('UTF-32', val)
-    pretty_printers_dict[re.compile('^std::bitset<.*>$')] = StdBitsetPrinter
-    pretty_printers_dict[re.compile('^std::deque<.*>$')] = StdDequePrinter
-    pretty_printers_dict[re.compile('^std::list<.*>$')] = StdListPrinter
+    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<.*>$')] = StdVectorPrinter
+    pretty_printers_dict[re.compile('^std::vector<.*>$')] = lambda val: StdVectorPrinter("std::vector", val)
     # 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)
+
     # 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)
@@ -619,6 +761,14 @@ def build_libstdcxx_dictionary ():
     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)
 
+    # 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)
+
 
     # Extensions.
     pretty_printers_dict[re.compile('^__gnu_cxx::slist<.*>$')] = StdSlistPrinter
@@ -626,8 +776,8 @@ def build_libstdcxx_dictionary ():
     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(val)
-        pretty_printers_dict[re.compile('^std::_List_const_iterator<.*>$')] = lambda val: StdListIteratorPrinter(val)
+        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)
@@ -635,6 +785,15 @@ def build_libstdcxx_dictionary ():
         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 = {}
 
 build_libstdcxx_dictionary ()