1 # Pretty-printers for libstc++.
3 # Copyright (C) 2008-2014 Free Software Foundation, Inc.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 # Try to use the new-style pretty-printing if available.
29 # Try to install type-printers.
30 _use_type_printing
= False
33 if hasattr(gdb
.types
, 'TypePrinter'):
34 _use_type_printing
= True
38 # Starting with the type ORIG, search for the member type NAME. This
39 # handles searching upward through superclasses. This is needed to
40 # work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615.
41 def find_type(orig
, name
):
42 typ
= orig
.strip_typedefs()
44 search
= str(typ
) + '::' + name
46 return gdb
.lookup_type(search
)
49 # The type was not found, so try the superclass. We only need
50 # to check the first superclass, so we don't bother with
51 # anything fancier here.
52 field
= typ
.fields()[0]
53 if not field
.is_base_class
:
54 raise ValueError("Cannot find type %s::%s" % (str(orig
), name
))
57 class SharedPointerPrinter
:
58 "Print a shared_ptr or weak_ptr"
60 def __init__ (self
, typename
, val
):
61 self
.typename
= typename
66 refcounts
= self
.val
['_M_refcount']['_M_pi']
68 usecount
= refcounts
['_M_use_count']
69 weakcount
= refcounts
['_M_weak_count']
71 state
= 'expired, weak %d' % weakcount
73 state
= 'count %d, weak %d' % (usecount
, weakcount
- 1)
74 return '%s (%s) %s' % (self
.typename
, state
, self
.val
['_M_ptr'])
76 class UniquePointerPrinter
:
79 def __init__ (self
, typename
, val
):
83 v
= self
.val
['_M_t']['_M_head_impl']
84 return ('std::unique_ptr<%s> containing %s' % (str(v
.type.target()),
91 def __init__(self
, nodetype
, head
):
92 self
.nodetype
= nodetype
93 self
.base
= head
['_M_next']
94 self
.head
= head
.address
101 if self
.base
== self
.head
:
103 elt
= self
.base
.cast(self
.nodetype
).dereference()
104 self
.base
= elt
['_M_next']
106 self
.count
= self
.count
+ 1
107 return ('[%d]' % count
, elt
['_M_data'])
109 def __init__(self
, typename
, val
):
110 self
.typename
= typename
114 nodetype
= find_type(self
.val
.type, '_Node')
115 nodetype
= nodetype
.strip_typedefs().pointer()
116 return self
._iterator
(nodetype
, self
.val
['_M_impl']['_M_node'])
119 if self
.val
['_M_impl']['_M_node'].address
== self
.val
['_M_impl']['_M_node']['_M_next']:
120 return 'empty %s' % (self
.typename
)
121 return '%s' % (self
.typename
)
123 class StdListIteratorPrinter
:
124 "Print std::list::iterator"
126 def __init__(self
, typename
, val
):
128 self
.typename
= typename
131 nodetype
= find_type(self
.val
.type, '_Node')
132 nodetype
= nodetype
.strip_typedefs().pointer()
133 return self
.val
['_M_node'].cast(nodetype
).dereference()['_M_data']
135 class StdSlistPrinter
:
136 "Print a __gnu_cxx::slist"
139 def __init__(self
, nodetype
, head
):
140 self
.nodetype
= nodetype
141 self
.base
= head
['_M_head']['_M_next']
150 elt
= self
.base
.cast(self
.nodetype
).dereference()
151 self
.base
= elt
['_M_next']
153 self
.count
= self
.count
+ 1
154 return ('[%d]' % count
, elt
['_M_data'])
156 def __init__(self
, typename
, val
):
160 nodetype
= find_type(self
.val
.type, '_Node')
161 nodetype
= nodetype
.strip_typedefs().pointer()
162 return self
._iterator
(nodetype
, self
.val
)
165 if self
.val
['_M_head']['_M_next'] == 0:
166 return 'empty __gnu_cxx::slist'
167 return '__gnu_cxx::slist'
169 class StdSlistIteratorPrinter
:
170 "Print __gnu_cxx::slist::iterator"
172 def __init__(self
, typename
, val
):
176 nodetype
= find_type(self
.val
.type, '_Node')
177 nodetype
= nodetype
.strip_typedefs().pointer()
178 return self
.val
['_M_node'].cast(nodetype
).dereference()['_M_data']
180 class StdVectorPrinter
:
181 "Print a std::vector"
184 def __init__ (self
, start
, finish
, bitvec
):
187 self
.item
= start
['_M_p']
188 self
.so
= start
['_M_offset']
189 self
.finish
= finish
['_M_p']
190 self
.fo
= finish
['_M_offset']
191 itype
= self
.item
.dereference().type
192 self
.isize
= 8 * itype
.sizeof
203 self
.count
= self
.count
+ 1
205 if self
.item
== self
.finish
and self
.so
>= self
.fo
:
207 elt
= self
.item
.dereference()
208 if elt
& (1 << self
.so
):
212 self
.so
= self
.so
+ 1
213 if self
.so
>= self
.isize
:
214 self
.item
= self
.item
+ 1
216 return ('[%d]' % count
, obit
)
218 if self
.item
== self
.finish
:
220 elt
= self
.item
.dereference()
221 self
.item
= self
.item
+ 1
222 return ('[%d]' % count
, elt
)
224 def __init__(self
, typename
, val
):
225 self
.typename
= typename
227 self
.is_bool
= val
.type.template_argument(0).code
== gdb
.TYPE_CODE_BOOL
230 return self
._iterator
(self
.val
['_M_impl']['_M_start'],
231 self
.val
['_M_impl']['_M_finish'],
235 start
= self
.val
['_M_impl']['_M_start']
236 finish
= self
.val
['_M_impl']['_M_finish']
237 end
= self
.val
['_M_impl']['_M_end_of_storage']
239 start
= self
.val
['_M_impl']['_M_start']['_M_p']
240 so
= self
.val
['_M_impl']['_M_start']['_M_offset']
241 finish
= self
.val
['_M_impl']['_M_finish']['_M_p']
242 fo
= self
.val
['_M_impl']['_M_finish']['_M_offset']
243 itype
= start
.dereference().type
244 bl
= 8 * itype
.sizeof
245 length
= (bl
- so
) + bl
* ((finish
- start
) - 1) + fo
246 capacity
= bl
* (end
- start
)
247 return ('%s<bool> of length %d, capacity %d'
248 % (self
.typename
, int (length
), int (capacity
)))
250 return ('%s of length %d, capacity %d'
251 % (self
.typename
, int (finish
- start
), int (end
- start
)))
253 def display_hint(self
):
256 class StdVectorIteratorPrinter
:
257 "Print std::vector::iterator"
259 def __init__(self
, typename
, val
):
263 return self
.val
['_M_current'].dereference()
265 class StdTuplePrinter
:
269 def __init__ (self
, head
):
272 # Set the base class as the initial head of the
274 nodes
= self
.head
.type.fields ()
276 # Set the actual head to the first pair.
277 self
.head
= self
.head
.cast (nodes
[0].type)
278 elif len (nodes
) != 0:
279 raise ValueError("Top of tuple tree does not consist of a single node.")
286 nodes
= self
.head
.type.fields ()
287 # Check for further recursions in the inheritance tree.
290 # Check that this iteration has an expected structure.
292 raise ValueError("Cannot parse more than 2 nodes in a tuple tree.")
294 # - Left node is the next recursion parent.
295 # - Right node is the actual class contained in the tuple.
297 # Process right node.
298 impl
= self
.head
.cast (nodes
[1].type)
300 # Process left node and set it as head.
301 self
.head
= self
.head
.cast (nodes
[0].type)
302 self
.count
= self
.count
+ 1
304 # Finally, check the implementation. If it is
305 # wrapped in _M_head_impl return that, otherwise return
307 fields
= impl
.type.fields ()
308 if len (fields
) < 1 or fields
[0].name
!= "_M_head_impl":
309 return ('[%d]' % self
.count
, impl
)
311 return ('[%d]' % self
.count
, impl
['_M_head_impl'])
313 def __init__ (self
, typename
, val
):
314 self
.typename
= typename
318 return self
._iterator
(self
.val
)
320 def to_string (self
):
321 if len (self
.val
.type.fields ()) == 0:
322 return 'empty %s' % (self
.typename
)
323 return '%s containing' % (self
.typename
)
325 class StdStackOrQueuePrinter
:
326 "Print a std::stack or std::queue"
328 def __init__ (self
, typename
, val
):
329 self
.typename
= typename
330 self
.visualizer
= gdb
.default_visualizer(val
['c'])
333 return self
.visualizer
.children()
335 def to_string (self
):
336 return '%s wrapping: %s' % (self
.typename
,
337 self
.visualizer
.to_string())
339 def display_hint (self
):
340 if hasattr (self
.visualizer
, 'display_hint'):
341 return self
.visualizer
.display_hint ()
344 class RbtreeIterator
:
345 def __init__(self
, rbtree
):
346 self
.size
= rbtree
['_M_t']['_M_impl']['_M_node_count']
347 self
.node
= rbtree
['_M_t']['_M_impl']['_M_header']['_M_left']
354 return int (self
.size
)
357 if self
.count
== self
.size
:
360 self
.count
= self
.count
+ 1
361 if self
.count
< self
.size
:
362 # Compute the next node.
364 if node
.dereference()['_M_right']:
365 node
= node
.dereference()['_M_right']
366 while node
.dereference()['_M_left']:
367 node
= node
.dereference()['_M_left']
369 parent
= node
.dereference()['_M_parent']
370 while node
== parent
.dereference()['_M_right']:
372 parent
= parent
.dereference()['_M_parent']
373 if node
.dereference()['_M_right'] != parent
:
378 def get_value_from_Rb_tree_node(node
):
379 """Returns the value held in an _Rb_tree_node<_Val>"""
381 member
= node
.type.fields()[1].name
382 if member
== '_M_value_field':
383 # C++03 implementation, node contains the value as a member
384 return node
['_M_value_field']
385 elif member
== '_M_storage':
386 # C++11 implementation, node stores value in __aligned_buffer
387 p
= node
['_M_storage']['_M_storage'].address
388 p
= p
.cast(node
.type.template_argument(0).pointer())
389 return p
.dereference()
392 raise ValueError("Unsupported implementation for %s" % str(node
.type))
394 # This is a pretty printer for std::_Rb_tree_iterator (which is
395 # std::map::iterator), and has nothing to do with the RbtreeIterator
397 class StdRbtreeIteratorPrinter
:
398 "Print std::map::iterator"
400 def __init__ (self
, typename
, val
):
403 def to_string (self
):
404 typename
= str(self
.val
.type.strip_typedefs()) + '::_Link_type'
405 nodetype
= gdb
.lookup_type(typename
).strip_typedefs()
406 node
= self
.val
.cast(nodetype
).dereference()
407 return get_value_from_Rb_tree_node(node
)
409 class StdDebugIteratorPrinter
:
410 "Print a debug enabled version of an iterator"
412 def __init__ (self
, typename
, val
):
415 # Just strip away the encapsulating __gnu_debug::_Safe_iterator
416 # and return the wrapped iterator value.
417 def to_string (self
):
418 itype
= self
.val
.type.template_argument(0)
419 return self
.val
['_M_current'].cast(itype
)
422 "Print a std::map or std::multimap"
424 # Turn an RbtreeIterator into a pretty-print iterator.
426 def __init__(self
, rbiter
, type):
435 if self
.count
% 2 == 0:
436 n
= self
.rbiter
.next()
437 n
= n
.cast(self
.type).dereference()
438 n
= get_value_from_Rb_tree_node(n
)
442 item
= self
.pair
['second']
443 result
= ('[%d]' % self
.count
, item
)
444 self
.count
= self
.count
+ 1
447 def __init__ (self
, typename
, val
):
448 self
.typename
= typename
451 def to_string (self
):
452 return '%s with %d elements' % (self
.typename
,
453 len (RbtreeIterator (self
.val
)))
456 rep_type
= find_type(self
.val
.type, '_Rep_type')
457 node
= find_type(rep_type
, '_Link_type')
458 node
= node
.strip_typedefs()
459 return self
._iter
(RbtreeIterator (self
.val
), node
)
461 def display_hint (self
):
465 "Print a std::set or std::multiset"
467 # Turn an RbtreeIterator into a pretty-print iterator.
469 def __init__(self
, rbiter
, type):
478 item
= self
.rbiter
.next()
479 item
= item
.cast(self
.type).dereference()
480 item
= get_value_from_Rb_tree_node(item
)
481 # FIXME: this is weird ... what to do?
482 # Maybe a 'set' display hint?
483 result
= ('[%d]' % self
.count
, item
)
484 self
.count
= self
.count
+ 1
487 def __init__ (self
, typename
, val
):
488 self
.typename
= typename
491 def to_string (self
):
492 return '%s with %d elements' % (self
.typename
,
493 len (RbtreeIterator (self
.val
)))
496 rep_type
= find_type(self
.val
.type, '_Rep_type')
497 node
= find_type(rep_type
, '_Link_type')
498 node
= node
.strip_typedefs()
499 return self
._iter
(RbtreeIterator (self
.val
), node
)
501 class StdBitsetPrinter
:
502 "Print a std::bitset"
504 def __init__(self
, typename
, val
):
505 self
.typename
= typename
508 def to_string (self
):
509 # If template_argument handled values, we could print the
510 # size. Or we could use a regexp on the type.
511 return '%s' % (self
.typename
)
514 words
= self
.val
['_M_w']
517 # The _M_w member can be either an unsigned long, or an
518 # array. This depends on the template specialization used.
519 # If it is a single long, convert to a single element list.
520 if wtype
.code
== gdb
.TYPE_CODE_ARRAY
:
521 tsize
= wtype
.target ().sizeof
526 nwords
= wtype
.sizeof
/ tsize
534 # Another spot where we could use 'set'?
535 result
.append(('[%d]' % (byte
* tsize
* 8 + bit
), 1))
541 class StdDequePrinter
:
545 def __init__(self
, node
, start
, end
, last
, buffer_size
):
550 self
.buffer_size
= buffer_size
557 if self
.p
== self
.last
:
560 result
= ('[%d]' % self
.count
, self
.p
.dereference())
561 self
.count
= self
.count
+ 1
563 # Advance the 'cur' pointer.
565 if self
.p
== self
.end
:
566 # If we got to the end of this bucket, move to the
568 self
.node
= self
.node
+ 1
569 self
.p
= self
.node
[0]
570 self
.end
= self
.p
+ self
.buffer_size
574 def __init__(self
, typename
, val
):
575 self
.typename
= typename
577 self
.elttype
= val
.type.template_argument(0)
578 size
= self
.elttype
.sizeof
580 self
.buffer_size
= int (512 / size
)
585 start
= self
.val
['_M_impl']['_M_start']
586 end
= self
.val
['_M_impl']['_M_finish']
588 delta_n
= end
['_M_node'] - start
['_M_node'] - 1
589 delta_s
= start
['_M_last'] - start
['_M_cur']
590 delta_e
= end
['_M_cur'] - end
['_M_first']
592 size
= self
.buffer_size
* delta_n
+ delta_s
+ delta_e
594 return '%s with %d elements' % (self
.typename
, long (size
))
597 start
= self
.val
['_M_impl']['_M_start']
598 end
= self
.val
['_M_impl']['_M_finish']
599 return self
._iter
(start
['_M_node'], start
['_M_cur'], start
['_M_last'],
600 end
['_M_cur'], self
.buffer_size
)
602 def display_hint (self
):
605 class StdDequeIteratorPrinter
:
606 "Print std::deque::iterator"
608 def __init__(self
, typename
, val
):
612 return self
.val
['_M_cur'].dereference()
614 class StdStringPrinter
:
615 "Print a std::basic_string of some kind"
617 def __init__(self
, typename
, val
):
621 # Make sure &string works, too.
623 if type.code
== gdb
.TYPE_CODE_REF
:
624 type = type.target ()
626 # Calculate the length of the string so that to_string returns
627 # the string according to length, not according to first null
629 ptr
= self
.val
['_M_dataplus']['_M_p']
630 realtype
= type.unqualified ().strip_typedefs ()
631 reptype
= gdb
.lookup_type (str (realtype
) + '::_Rep').pointer ()
632 header
= ptr
.cast(reptype
) - 1
633 len = header
.dereference ()['_M_length']
634 if hasattr(ptr
, "lazy_string"):
635 return ptr
.lazy_string (length
= len)
636 return ptr
.string (length
= len)
638 def display_hint (self
):
641 class Tr1HashtableIterator
:
642 def __init__ (self
, hash):
643 self
.buckets
= hash['_M_buckets']
645 self
.bucket_count
= hash['_M_bucket_count']
646 self
.node_type
= find_type(hash.type, '_Node').pointer()
648 while self
.bucket
!= self
.bucket_count
:
649 self
.node
= self
.buckets
[self
.bucket
]
652 self
.bucket
= self
.bucket
+ 1
660 node
= self
.node
.cast(self
.node_type
)
661 result
= node
.dereference()['_M_v']
662 self
.node
= node
.dereference()['_M_next'];
664 self
.bucket
= self
.bucket
+ 1
665 while self
.bucket
!= self
.bucket_count
:
666 self
.node
= self
.buckets
[self
.bucket
]
669 self
.bucket
= self
.bucket
+ 1
672 class StdHashtableIterator
:
673 def __init__(self
, hash):
674 self
.node
= hash['_M_before_begin']['_M_nxt']
675 self
.node_type
= find_type(hash.type, '__node_type').pointer()
683 elt
= self
.node
.cast(self
.node_type
).dereference()
684 self
.node
= elt
['_M_nxt']
685 valptr
= elt
['_M_storage'].address
686 valptr
= valptr
.cast(elt
.type.template_argument(0).pointer())
687 return valptr
.dereference()
689 class Tr1UnorderedSetPrinter
:
690 "Print a tr1::unordered_set"
692 def __init__ (self
, typename
, val
):
693 self
.typename
= typename
696 def hashtable (self
):
697 if self
.typename
.startswith('std::tr1'):
699 return self
.val
['_M_h']
701 def to_string (self
):
702 return '%s with %d elements' % (self
.typename
, self
.hashtable()['_M_element_count'])
705 def format_count (i
):
709 counter
= itertools
.imap (self
.format_count
, itertools
.count())
710 if self
.typename
.startswith('std::tr1'):
711 return itertools
.izip (counter
, Tr1HashtableIterator (self
.hashtable()))
712 return itertools
.izip (counter
, StdHashtableIterator (self
.hashtable()))
714 class Tr1UnorderedMapPrinter
:
715 "Print a tr1::unordered_map"
717 def __init__ (self
, typename
, val
):
718 self
.typename
= typename
721 def hashtable (self
):
722 if self
.typename
.startswith('std::tr1'):
724 return self
.val
['_M_h']
726 def to_string (self
):
727 return '%s with %d elements' % (self
.typename
, self
.hashtable()['_M_element_count'])
736 def format_one (elt
):
737 return (elt
['first'], elt
['second'])
740 def format_count (i
):
744 counter
= itertools
.imap (self
.format_count
, itertools
.count())
745 # Map over the hash table and flatten the result.
746 if self
.typename
.startswith('std::tr1'):
747 data
= self
.flatten (itertools
.imap (self
.format_one
, Tr1HashtableIterator (self
.hashtable())))
748 # Zip the two iterators together.
749 return itertools
.izip (counter
, data
)
750 data
= self
.flatten (itertools
.imap (self
.format_one
, StdHashtableIterator (self
.hashtable())))
751 # Zip the two iterators together.
752 return itertools
.izip (counter
, data
)
755 def display_hint (self
):
758 class StdForwardListPrinter
:
759 "Print a std::forward_list"
762 def __init__(self
, nodetype
, head
):
763 self
.nodetype
= nodetype
764 self
.base
= head
['_M_next']
773 elt
= self
.base
.cast(self
.nodetype
).dereference()
774 self
.base
= elt
['_M_next']
776 self
.count
= self
.count
+ 1
777 valptr
= elt
['_M_storage'].address
778 valptr
= valptr
.cast(elt
.type.template_argument(0).pointer())
779 return ('[%d]' % count
, valptr
.dereference())
781 def __init__(self
, typename
, val
):
783 self
.typename
= typename
786 nodetype
= find_type(self
.val
.type, '_Node')
787 nodetype
= nodetype
.strip_typedefs().pointer()
788 return self
._iterator
(nodetype
, self
.val
['_M_impl']['_M_head'])
791 if self
.val
['_M_impl']['_M_head']['_M_next'] == 0:
792 return 'empty %s' % (self
.typename
)
793 return '%s' % (self
.typename
)
796 # A "regular expression" printer which conforms to the
797 # "SubPrettyPrinter" protocol from gdb.printing.
798 class RxPrinter(object):
799 def __init__(self
, name
, function
):
800 super(RxPrinter
, self
).__init
__()
802 self
.function
= function
805 def invoke(self
, value
):
809 if value
.type.code
== gdb
.TYPE_CODE_REF
:
810 if hasattr(gdb
.Value
,"referenced_value"):
811 value
= value
.referenced_value()
813 return self
.function(self
.name
, value
)
815 # A pretty-printer that conforms to the "PrettyPrinter" protocol from
816 # gdb.printing. It can also be used directly as an old-style printer.
817 class Printer(object):
818 def __init__(self
, name
):
819 super(Printer
, self
).__init
__()
821 self
.subprinters
= []
824 self
.compiled_rx
= re
.compile('^([a-zA-Z0-9_:]+)<.*>$')
826 def add(self
, name
, function
):
827 # A small sanity check.
829 if not self
.compiled_rx
.match(name
+ '<>'):
830 raise ValueError('libstdc++ programming error: "%s" does not match' % name
)
831 printer
= RxPrinter(name
, function
)
832 self
.subprinters
.append(printer
)
833 self
.lookup
[name
] = printer
835 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
836 def add_version(self
, base
, name
, function
):
837 self
.add(base
+ name
, function
)
838 self
.add(base
+ '__7::' + name
, function
)
840 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
841 def add_container(self
, base
, name
, function
):
842 self
.add_version(base
, name
, function
)
843 self
.add_version(base
+ '__cxx1998::', name
, function
)
846 def get_basic_type(type):
847 # If it points to a reference, get the reference.
848 if type.code
== gdb
.TYPE_CODE_REF
:
849 type = type.target ()
851 # Get the unqualified type, stripped of typedefs.
852 type = type.unqualified ().strip_typedefs ()
856 def __call__(self
, val
):
857 typename
= self
.get_basic_type(val
.type)
861 # All the types we match are template types, so we can use a
863 match
= self
.compiled_rx
.match(typename
)
867 basename
= match
.group(1)
869 if val
.type.code
== gdb
.TYPE_CODE_REF
:
870 if hasattr(gdb
.Value
,"referenced_value"):
871 val
= val
.referenced_value()
873 if basename
in self
.lookup
:
874 return self
.lookup
[basename
].invoke(val
)
876 # Cannot find a pretty printer. Return None.
879 libstdcxx_printer
= None
881 class FilteringTypePrinter(object):
882 def __init__(self
, match
, name
):
887 class _recognizer(object):
888 def __init__(self
, match
, name
):
893 def recognize(self
, type_obj
):
894 if type_obj
.tag
is None:
897 if self
.type_obj
is None:
898 if not self
.match
in type_obj
.tag
:
899 # Filter didn't match.
902 self
.type_obj
= gdb
.lookup_type(self
.name
).strip_typedefs()
905 if self
.type_obj
== type_obj
:
909 def instantiate(self
):
910 return self
._recognizer
(self
.match
, self
.name
)
912 def add_one_type_printer(obj
, match
, name
):
913 printer
= FilteringTypePrinter(match
, 'std::' + name
)
914 gdb
.types
.register_type_printer(obj
, printer
)
916 def register_type_printers(obj
):
917 global _use_type_printing
919 if not _use_type_printing
:
922 for pfx
in ('', 'w'):
923 add_one_type_printer(obj
, 'basic_string', pfx
+ 'string')
924 add_one_type_printer(obj
, 'basic_ios', pfx
+ 'ios')
925 add_one_type_printer(obj
, 'basic_streambuf', pfx
+ 'streambuf')
926 add_one_type_printer(obj
, 'basic_istream', pfx
+ 'istream')
927 add_one_type_printer(obj
, 'basic_ostream', pfx
+ 'ostream')
928 add_one_type_printer(obj
, 'basic_iostream', pfx
+ 'iostream')
929 add_one_type_printer(obj
, 'basic_stringbuf', pfx
+ 'stringbuf')
930 add_one_type_printer(obj
, 'basic_istringstream',
931 pfx
+ 'istringstream')
932 add_one_type_printer(obj
, 'basic_ostringstream',
933 pfx
+ 'ostringstream')
934 add_one_type_printer(obj
, 'basic_stringstream',
935 pfx
+ 'stringstream')
936 add_one_type_printer(obj
, 'basic_filebuf', pfx
+ 'filebuf')
937 add_one_type_printer(obj
, 'basic_ifstream', pfx
+ 'ifstream')
938 add_one_type_printer(obj
, 'basic_ofstream', pfx
+ 'ofstream')
939 add_one_type_printer(obj
, 'basic_fstream', pfx
+ 'fstream')
940 add_one_type_printer(obj
, 'basic_regex', pfx
+ 'regex')
941 add_one_type_printer(obj
, 'sub_match', pfx
+ 'csub_match')
942 add_one_type_printer(obj
, 'sub_match', pfx
+ 'ssub_match')
943 add_one_type_printer(obj
, 'match_results', pfx
+ 'cmatch')
944 add_one_type_printer(obj
, 'match_results', pfx
+ 'smatch')
945 add_one_type_printer(obj
, 'regex_iterator', pfx
+ 'cregex_iterator')
946 add_one_type_printer(obj
, 'regex_iterator', pfx
+ 'sregex_iterator')
947 add_one_type_printer(obj
, 'regex_token_iterator',
948 pfx
+ 'cregex_token_iterator')
949 add_one_type_printer(obj
, 'regex_token_iterator',
950 pfx
+ 'sregex_token_iterator')
952 # Note that we can't have a printer for std::wstreampos, because
953 # it shares the same underlying type as std::streampos.
954 add_one_type_printer(obj
, 'fpos', 'streampos')
955 add_one_type_printer(obj
, 'basic_string', 'u16string')
956 add_one_type_printer(obj
, 'basic_string', 'u32string')
958 for dur
in ('nanoseconds', 'microseconds', 'milliseconds',
959 'seconds', 'minutes', 'hours'):
960 add_one_type_printer(obj
, 'duration', dur
)
962 add_one_type_printer(obj
, 'linear_congruential_engine', 'minstd_rand0')
963 add_one_type_printer(obj
, 'linear_congruential_engine', 'minstd_rand')
964 add_one_type_printer(obj
, 'mersenne_twister_engine', 'mt19937')
965 add_one_type_printer(obj
, 'mersenne_twister_engine', 'mt19937_64')
966 add_one_type_printer(obj
, 'subtract_with_carry_engine', 'ranlux24_base')
967 add_one_type_printer(obj
, 'subtract_with_carry_engine', 'ranlux48_base')
968 add_one_type_printer(obj
, 'discard_block_engine', 'ranlux24')
969 add_one_type_printer(obj
, 'discard_block_engine', 'ranlux48')
970 add_one_type_printer(obj
, 'shuffle_order_engine', 'knuth_b')
972 def register_libstdcxx_printers (obj
):
973 "Register libstdc++ pretty-printers with objfile Obj."
976 global libstdcxx_printer
979 gdb
.printing
.register_pretty_printer(obj
, libstdcxx_printer
)
983 obj
.pretty_printers
.append(libstdcxx_printer
)
985 register_type_printers(obj
)
987 def build_libstdcxx_dictionary ():
988 global libstdcxx_printer
990 libstdcxx_printer
= Printer("libstdc++-v6")
992 # For _GLIBCXX_BEGIN_NAMESPACE_VERSION.
994 # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
995 container
= '(__cxx1998::' + vers
+ ')?'
997 # libstdc++ objects requiring pretty-printing.
999 # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html
1000 libstdcxx_printer
.add_version('std::', 'basic_string', StdStringPrinter
)
1001 libstdcxx_printer
.add_container('std::', 'bitset', StdBitsetPrinter
)
1002 libstdcxx_printer
.add_container('std::', 'deque', StdDequePrinter
)
1003 libstdcxx_printer
.add_container('std::', 'list', StdListPrinter
)
1004 libstdcxx_printer
.add_container('std::', 'map', StdMapPrinter
)
1005 libstdcxx_printer
.add_container('std::', 'multimap', StdMapPrinter
)
1006 libstdcxx_printer
.add_container('std::', 'multiset', StdSetPrinter
)
1007 libstdcxx_printer
.add_version('std::', 'priority_queue',
1008 StdStackOrQueuePrinter
)
1009 libstdcxx_printer
.add_version('std::', 'queue', StdStackOrQueuePrinter
)
1010 libstdcxx_printer
.add_version('std::', 'tuple', StdTuplePrinter
)
1011 libstdcxx_printer
.add_container('std::', 'set', StdSetPrinter
)
1012 libstdcxx_printer
.add_version('std::', 'stack', StdStackOrQueuePrinter
)
1013 libstdcxx_printer
.add_version('std::', 'unique_ptr', UniquePointerPrinter
)
1014 libstdcxx_printer
.add_container('std::', 'vector', StdVectorPrinter
)
1017 # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG.
1018 libstdcxx_printer
.add('std::__debug::bitset', StdBitsetPrinter
)
1019 libstdcxx_printer
.add('std::__debug::deque', StdDequePrinter
)
1020 libstdcxx_printer
.add('std::__debug::list', StdListPrinter
)
1021 libstdcxx_printer
.add('std::__debug::map', StdMapPrinter
)
1022 libstdcxx_printer
.add('std::__debug::multimap', StdMapPrinter
)
1023 libstdcxx_printer
.add('std::__debug::multiset', StdSetPrinter
)
1024 libstdcxx_printer
.add('std::__debug::priority_queue',
1025 StdStackOrQueuePrinter
)
1026 libstdcxx_printer
.add('std::__debug::queue', StdStackOrQueuePrinter
)
1027 libstdcxx_printer
.add('std::__debug::set', StdSetPrinter
)
1028 libstdcxx_printer
.add('std::__debug::stack', StdStackOrQueuePrinter
)
1029 libstdcxx_printer
.add('std::__debug::unique_ptr', UniquePointerPrinter
)
1030 libstdcxx_printer
.add('std::__debug::vector', StdVectorPrinter
)
1032 # These are the TR1 and C++0x printers.
1033 # For array - the default GDB pretty-printer seems reasonable.
1034 libstdcxx_printer
.add_version('std::', 'shared_ptr', SharedPointerPrinter
)
1035 libstdcxx_printer
.add_version('std::', 'weak_ptr', SharedPointerPrinter
)
1036 libstdcxx_printer
.add_container('std::', 'unordered_map',
1037 Tr1UnorderedMapPrinter
)
1038 libstdcxx_printer
.add_container('std::', 'unordered_set',
1039 Tr1UnorderedSetPrinter
)
1040 libstdcxx_printer
.add_container('std::', 'unordered_multimap',
1041 Tr1UnorderedMapPrinter
)
1042 libstdcxx_printer
.add_container('std::', 'unordered_multiset',
1043 Tr1UnorderedSetPrinter
)
1044 libstdcxx_printer
.add_container('std::', 'forward_list',
1045 StdForwardListPrinter
)
1047 libstdcxx_printer
.add_version('std::tr1::', 'shared_ptr', SharedPointerPrinter
)
1048 libstdcxx_printer
.add_version('std::tr1::', 'weak_ptr', SharedPointerPrinter
)
1049 libstdcxx_printer
.add_version('std::tr1::', 'unordered_map',
1050 Tr1UnorderedMapPrinter
)
1051 libstdcxx_printer
.add_version('std::tr1::', 'unordered_set',
1052 Tr1UnorderedSetPrinter
)
1053 libstdcxx_printer
.add_version('std::tr1::', 'unordered_multimap',
1054 Tr1UnorderedMapPrinter
)
1055 libstdcxx_printer
.add_version('std::tr1::', 'unordered_multiset',
1056 Tr1UnorderedSetPrinter
)
1058 # These are the C++0x printer registrations for -D_GLIBCXX_DEBUG cases.
1059 # The tr1 namespace printers do not seem to have any debug
1060 # equivalents, so do no register them.
1061 libstdcxx_printer
.add('std::__debug::unordered_map',
1062 Tr1UnorderedMapPrinter
)
1063 libstdcxx_printer
.add('std::__debug::unordered_set',
1064 Tr1UnorderedSetPrinter
)
1065 libstdcxx_printer
.add('std::__debug::unordered_multimap',
1066 Tr1UnorderedMapPrinter
)
1067 libstdcxx_printer
.add('std::__debug::unordered_multiset',
1068 Tr1UnorderedSetPrinter
)
1069 libstdcxx_printer
.add('std::__debug::forward_list',
1070 StdForwardListPrinter
)
1074 libstdcxx_printer
.add_version('__gnu_cxx::', 'slist', StdSlistPrinter
)
1077 # These shouldn't be necessary, if GDB "print *i" worked.
1078 # But it often doesn't, so here they are.
1079 libstdcxx_printer
.add_container('std::', '_List_iterator',
1080 StdListIteratorPrinter
)
1081 libstdcxx_printer
.add_container('std::', '_List_const_iterator',
1082 StdListIteratorPrinter
)
1083 libstdcxx_printer
.add_version('std::', '_Rb_tree_iterator',
1084 StdRbtreeIteratorPrinter
)
1085 libstdcxx_printer
.add_version('std::', '_Rb_tree_const_iterator',
1086 StdRbtreeIteratorPrinter
)
1087 libstdcxx_printer
.add_container('std::', '_Deque_iterator',
1088 StdDequeIteratorPrinter
)
1089 libstdcxx_printer
.add_container('std::', '_Deque_const_iterator',
1090 StdDequeIteratorPrinter
)
1091 libstdcxx_printer
.add_version('__gnu_cxx::', '__normal_iterator',
1092 StdVectorIteratorPrinter
)
1093 libstdcxx_printer
.add_version('__gnu_cxx::', '_Slist_iterator',
1094 StdSlistIteratorPrinter
)
1096 # Debug (compiled with -D_GLIBCXX_DEBUG) printer
1097 # registrations. The Rb_tree debug iterator when unwrapped
1098 # from the encapsulating __gnu_debug::_Safe_iterator does not
1099 # have the __norm namespace. Just use the existing printer
1100 # registration for that.
1101 libstdcxx_printer
.add('__gnu_debug::_Safe_iterator',
1102 StdDebugIteratorPrinter
)
1103 libstdcxx_printer
.add('std::__norm::_List_iterator',
1104 StdListIteratorPrinter
)
1105 libstdcxx_printer
.add('std::__norm::_List_const_iterator',
1106 StdListIteratorPrinter
)
1107 libstdcxx_printer
.add('std::__norm::_Deque_const_iterator',
1108 StdDequeIteratorPrinter
)
1109 libstdcxx_printer
.add('std::__norm::_Deque_iterator',
1110 StdDequeIteratorPrinter
)
1112 build_libstdcxx_dictionary ()