1# Pretty-printers for libstc++. 2 3# Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. 4 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. 9# 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. 14# 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/>. 17 18import gdb 19import itertools 20import re 21 22class StdPointerPrinter: 23 "Print a smart pointer of some kind" 24 25 def __init__ (self, typename, val): 26 self.typename = typename 27 self.val = val 28 29 def to_string (self): 30 if self.val['_M_refcount']['_M_pi'] == 0: 31 return '%s (empty) %s' % (self.typename, self.val['_M_ptr']) 32 return '%s (count %d) %s' % (self.typename, 33 self.val['_M_refcount']['_M_pi']['_M_use_count'], 34 self.val['_M_ptr']) 35 36class UniquePointerPrinter: 37 "Print a unique_ptr" 38 39 def __init__ (self, val): 40 self.val = val 41 42 def to_string (self): 43 return self.val['_M_t'] 44 45class StdListPrinter: 46 "Print a std::list" 47 48 class _iterator: 49 def __init__(self, nodetype, head): 50 self.nodetype = nodetype 51 self.base = head['_M_next'] 52 self.head = head.address 53 self.count = 0 54 55 def __iter__(self): 56 return self 57 58 def next(self): 59 if self.base == self.head: 60 raise StopIteration 61 elt = self.base.cast(self.nodetype).dereference() 62 self.base = elt['_M_next'] 63 count = self.count 64 self.count = self.count + 1 65 return ('[%d]' % count, elt['_M_data']) 66 67 def __init__(self, typename, val): 68 self.typename = typename 69 self.val = val 70 71 def children(self): 72 itype = self.val.type.template_argument(0) 73 # If the inferior program is compiled with -D_GLIBCXX_DEBUG 74 # some of the internal implementation details change. 75 if self.typename == "std::list": 76 nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer() 77 elif self.typename == "std::__debug::list": 78 nodetype = gdb.lookup_type('std::__norm::_List_node<%s>' % itype).pointer() 79 else: 80 raise ValueError, "Cannot cast list node for list printer." 81 return self._iterator(nodetype, self.val['_M_impl']['_M_node']) 82 83 def to_string(self): 84 if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']: 85 return 'empty %s' % (self.typename) 86 return '%s' % (self.typename) 87 88class StdListIteratorPrinter: 89 "Print std::list::iterator" 90 91 def __init__(self, typename, val): 92 self.val = val 93 self.typename = typename 94 95 def to_string(self): 96 itype = self.val.type.template_argument(0) 97 # If the inferior program is compiled with -D_GLIBCXX_DEBUG 98 # some of the internal implementation details change. 99 if self.typename == "std::_List_iterator" or self.typename == "std::_List_const_iterator": 100 nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer() 101 elif self.typename == "std::__norm::_List_iterator" or self.typename == "std::__norm::_List_const_iterator": 102 nodetype = gdb.lookup_type('std::__norm::_List_node<%s>' % itype).pointer() 103 else: 104 raise ValueError, "Cannot cast list node for list iterator printer." 105 return self.val['_M_node'].cast(nodetype).dereference()['_M_data'] 106 107class StdSlistPrinter: 108 "Print a __gnu_cxx::slist" 109 110 class _iterator: 111 def __init__(self, nodetype, head): 112 self.nodetype = nodetype 113 self.base = head['_M_head']['_M_next'] 114 self.count = 0 115 116 def __iter__(self): 117 return self 118 119 def next(self): 120 if self.base == 0: 121 raise StopIteration 122 elt = self.base.cast(self.nodetype).dereference() 123 self.base = elt['_M_next'] 124 count = self.count 125 self.count = self.count + 1 126 return ('[%d]' % count, elt['_M_data']) 127 128 def __init__(self, val): 129 self.val = val 130 131 def children(self): 132 itype = self.val.type.template_argument(0) 133 nodetype = gdb.lookup_type('__gnu_cxx::_Slist_node<%s>' % itype).pointer() 134 return self._iterator(nodetype, self.val) 135 136 def to_string(self): 137 if self.val['_M_head']['_M_next'] == 0: 138 return 'empty __gnu_cxx::slist' 139 return '__gnu_cxx::slist' 140 141class StdSlistIteratorPrinter: 142 "Print __gnu_cxx::slist::iterator" 143 144 def __init__(self, val): 145 self.val = val 146 147 def to_string(self): 148 itype = self.val.type.template_argument(0) 149 nodetype = gdb.lookup_type('__gnu_cxx::_Slist_node<%s>' % itype).pointer() 150 return self.val['_M_node'].cast(nodetype).dereference()['_M_data'] 151 152class StdVectorPrinter: 153 "Print a std::vector" 154 155 class _iterator: 156 def __init__ (self, start, finish, bitvec): 157 self.bitvec = bitvec 158 if bitvec: 159 self.item = start['_M_p'] 160 self.so = start['_M_offset'] 161 self.finish = finish['_M_p'] 162 self.fo = finish['_M_offset'] 163 itype = self.item.dereference().type 164 self.isize = 8 * itype.sizeof 165 else: 166 self.item = start 167 self.finish = finish 168 self.count = 0 169 170 def __iter__(self): 171 return self 172 173 def next(self): 174 count = self.count 175 self.count = self.count + 1 176 if self.bitvec: 177 if self.item == self.finish and self.so >= self.fo: 178 raise StopIteration 179 elt = self.item.dereference() 180 if elt & (1 << self.so): 181 obit = 1 182 else: 183 obit = 0 184 self.so = self.so + 1 185 if self.so >= self.isize: 186 self.item = self.item + 1 187 self.so = 0 188 return ('[%d]' % count, obit) 189 else: 190 if self.item == self.finish: 191 raise StopIteration 192 elt = self.item.dereference() 193 self.item = self.item + 1 194 return ('[%d]' % count, elt) 195 196 def __init__(self, typename, val): 197 self.typename = typename 198 self.val = val 199 self.is_bool = val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL 200 201 def children(self): 202 return self._iterator(self.val['_M_impl']['_M_start'], 203 self.val['_M_impl']['_M_finish'], 204 self.is_bool) 205 206 def to_string(self): 207 start = self.val['_M_impl']['_M_start'] 208 finish = self.val['_M_impl']['_M_finish'] 209 end = self.val['_M_impl']['_M_end_of_storage'] 210 if self.is_bool: 211 start = self.val['_M_impl']['_M_start']['_M_p'] 212 so = self.val['_M_impl']['_M_start']['_M_offset'] 213 finish = self.val['_M_impl']['_M_finish']['_M_p'] 214 fo = self.val['_M_impl']['_M_finish']['_M_offset'] 215 itype = start.dereference().type 216 bl = 8 * itype.sizeof 217 length = (bl - so) + bl * ((finish - start) - 1) + fo 218 capacity = bl * (end - start) 219 return ('%s<bool> of length %d, capacity %d' 220 % (self.typename, int (length), int (capacity))) 221 else: 222 return ('%s of length %d, capacity %d' 223 % (self.typename, int (finish - start), int (end - start))) 224 225 def display_hint(self): 226 return 'array' 227 228class StdVectorIteratorPrinter: 229 "Print std::vector::iterator" 230 231 def __init__(self, val): 232 self.val = val 233 234 def to_string(self): 235 return self.val['_M_current'].dereference() 236 237class StdTuplePrinter: 238 "Print a std::tuple" 239 240 class _iterator: 241 def __init__ (self, head): 242 self.head = head 243 244 # Set the base class as the initial head of the 245 # tuple. 246 nodes = self.head.type.fields () 247 if len (nodes) != 1: 248 raise ValueError, "Top of tuple tree does not consist of a single node." 249 250 # Set the actual head to the first pair. 251 self.head = self.head.cast (nodes[0].type) 252 self.count = 0 253 254 def __iter__ (self): 255 return self 256 257 def next (self): 258 nodes = self.head.type.fields () 259 # Check for further recursions in the inheritance tree. 260 if len (nodes) == 0: 261 raise StopIteration 262 # Check that this iteration has an expected structure. 263 if len (nodes) != 2: 264 raise ValueError, "Cannot parse more than 2 nodes in a tuple tree." 265 266 # - Left node is the next recursion parent. 267 # - Right node is the actual class contained in the tuple. 268 269 # Process right node. 270 impl = self.head.cast (nodes[1].type) 271 272 # Process left node and set it as head. 273 self.head = self.head.cast (nodes[0].type) 274 self.count = self.count + 1 275 276 # Finally, check the implementation. If it is 277 # wrapped in _M_head_impl return that, otherwise return 278 # the value "as is". 279 fields = impl.type.fields () 280 if len (fields) < 1 or fields[0].name != "_M_head_impl": 281 return ('[%d]' % self.count, impl) 282 else: 283 return ('[%d]' % self.count, impl['_M_head_impl']) 284 285 def __init__ (self, typename, val): 286 self.typename = typename 287 self.val = val; 288 289 def children (self): 290 return self._iterator (self.val) 291 292 def to_string (self): 293 return '%s containing' % (self.typename) 294 295class StdStackOrQueuePrinter: 296 "Print a std::stack or std::queue" 297 298 def __init__ (self, typename, val): 299 self.typename = typename 300 self.visualizer = gdb.default_visualizer(val['c']) 301 302 def children (self): 303 return self.visualizer.children() 304 305 def to_string (self): 306 return '%s wrapping: %s' % (self.typename, 307 self.visualizer.to_string()) 308 309 def display_hint (self): 310 if hasattr (self.visualizer, 'display_hint'): 311 return self.visualizer.display_hint () 312 return None 313 314class RbtreeIterator: 315 def __init__(self, rbtree): 316 self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] 317 self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] 318 self.count = 0 319 320 def __iter__(self): 321 return self 322 323 def __len__(self): 324 return int (self.size) 325 326 def next(self): 327 if self.count == self.size: 328 raise StopIteration 329 result = self.node 330 self.count = self.count + 1 331 if self.count < self.size: 332 # Compute the next node. 333 node = self.node 334 if node.dereference()['_M_right']: 335 node = node.dereference()['_M_right'] 336 while node.dereference()['_M_left']: 337 node = node.dereference()['_M_left'] 338 else: 339 parent = node.dereference()['_M_parent'] 340 while node == parent.dereference()['_M_right']: 341 node = parent 342 parent = parent.dereference()['_M_parent'] 343 if node.dereference()['_M_right'] != parent: 344 node = parent 345 self.node = node 346 return result 347 348# This is a pretty printer for std::_Rb_tree_iterator (which is 349# std::map::iterator), and has nothing to do with the RbtreeIterator 350# class above. 351class StdRbtreeIteratorPrinter: 352 "Print std::map::iterator" 353 354 def __init__ (self, val): 355 self.val = val 356 357 def to_string (self): 358 valuetype = self.val.type.template_argument(0) 359 nodetype = gdb.lookup_type('std::_Rb_tree_node < %s >' % valuetype) 360 nodetype = nodetype.pointer() 361 return self.val.cast(nodetype).dereference()['_M_value_field'] 362 363class StdDebugIteratorPrinter: 364 "Print a debug enabled version of an iterator" 365 366 def __init__ (self, val): 367 self.val = val 368 369 # Just strip away the encapsulating __gnu_debug::_Safe_iterator 370 # and return the wrapped iterator value. 371 def to_string (self): 372 itype = self.val.type.template_argument(0) 373 return self.val['_M_current'].cast(itype) 374 375class StdMapPrinter: 376 "Print a std::map or std::multimap" 377 378 # Turn an RbtreeIterator into a pretty-print iterator. 379 class _iter: 380 def __init__(self, rbiter, type): 381 self.rbiter = rbiter 382 self.count = 0 383 self.type = type 384 385 def __iter__(self): 386 return self 387 388 def next(self): 389 if self.count % 2 == 0: 390 n = self.rbiter.next() 391 n = n.cast(self.type).dereference()['_M_value_field'] 392 self.pair = n 393 item = n['first'] 394 else: 395 item = self.pair['second'] 396 result = ('[%d]' % self.count, item) 397 self.count = self.count + 1 398 return result 399 400 def __init__ (self, typename, val): 401 self.typename = typename 402 self.val = val 403 404 def to_string (self): 405 return '%s with %d elements' % (self.typename, 406 len (RbtreeIterator (self.val))) 407 408 def children (self): 409 keytype = self.val.type.template_argument(0).const() 410 valuetype = self.val.type.template_argument(1) 411 nodetype = gdb.lookup_type('std::_Rb_tree_node< std::pair< %s, %s > >' % (keytype, valuetype)) 412 nodetype = nodetype.pointer() 413 return self._iter (RbtreeIterator (self.val), nodetype) 414 415 def display_hint (self): 416 return 'map' 417 418class StdSetPrinter: 419 "Print a std::set or std::multiset" 420 421 # Turn an RbtreeIterator into a pretty-print iterator. 422 class _iter: 423 def __init__(self, rbiter, type): 424 self.rbiter = rbiter 425 self.count = 0 426 self.type = type 427 428 def __iter__(self): 429 return self 430 431 def next(self): 432 item = self.rbiter.next() 433 item = item.cast(self.type).dereference()['_M_value_field'] 434 # FIXME: this is weird ... what to do? 435 # Maybe a 'set' display hint? 436 result = ('[%d]' % self.count, item) 437 self.count = self.count + 1 438 return result 439 440 def __init__ (self, typename, val): 441 self.typename = typename 442 self.val = val 443 444 def to_string (self): 445 return '%s with %d elements' % (self.typename, 446 len (RbtreeIterator (self.val))) 447 448 def children (self): 449 keytype = self.val.type.template_argument(0) 450 nodetype = gdb.lookup_type('std::_Rb_tree_node< %s >' % keytype).pointer() 451 return self._iter (RbtreeIterator (self.val), nodetype) 452 453class StdBitsetPrinter: 454 "Print a std::bitset" 455 456 def __init__(self, typename, val): 457 self.typename = typename 458 self.val = val 459 460 def to_string (self): 461 # If template_argument handled values, we could print the 462 # size. Or we could use a regexp on the type. 463 return '%s' % (self.typename) 464 465 def children (self): 466 words = self.val['_M_w'] 467 wtype = words.type 468 469 # The _M_w member can be either an unsigned long, or an 470 # array. This depends on the template specialization used. 471 # If it is a single long, convert to a single element list. 472 if wtype.code == gdb.TYPE_CODE_ARRAY: 473 tsize = wtype.target ().sizeof 474 else: 475 words = [words] 476 tsize = wtype.sizeof 477 478 nwords = wtype.sizeof / tsize 479 result = [] 480 byte = 0 481 while byte < nwords: 482 w = words[byte] 483 bit = 0 484 while w != 0: 485 if (w & 1) != 0: 486 # Another spot where we could use 'set'? 487 result.append(('[%d]' % (byte * tsize * 8 + bit), 1)) 488 bit = bit + 1 489 w = w >> 1 490 byte = byte + 1 491 return result 492 493class StdDequePrinter: 494 "Print a std::deque" 495 496 class _iter: 497 def __init__(self, node, start, end, last, buffer_size): 498 self.node = node 499 self.p = start 500 self.end = end 501 self.last = last 502 self.buffer_size = buffer_size 503 self.count = 0 504 505 def __iter__(self): 506 return self 507 508 def next(self): 509 if self.p == self.last: 510 raise StopIteration 511 512 result = ('[%d]' % self.count, self.p.dereference()) 513 self.count = self.count + 1 514 515 # Advance the 'cur' pointer. 516 self.p = self.p + 1 517 if self.p == self.end: 518 # If we got to the end of this bucket, move to the 519 # next bucket. 520 self.node = self.node + 1 521 self.p = self.node[0] 522 self.end = self.p + self.buffer_size 523 524 return result 525 526 def __init__(self, typename, val): 527 self.typename = typename 528 self.val = val 529 self.elttype = val.type.template_argument(0) 530 size = self.elttype.sizeof 531 if size < 512: 532 self.buffer_size = int (512 / size) 533 else: 534 self.buffer_size = 1 535 536 def to_string(self): 537 start = self.val['_M_impl']['_M_start'] 538 end = self.val['_M_impl']['_M_finish'] 539 540 delta_n = end['_M_node'] - start['_M_node'] - 1 541 delta_s = start['_M_last'] - start['_M_cur'] 542 delta_e = end['_M_cur'] - end['_M_first'] 543 544 size = self.buffer_size * delta_n + delta_s + delta_e 545 546 return '%s with %d elements' % (self.typename, long (size)) 547 548 def children(self): 549 start = self.val['_M_impl']['_M_start'] 550 end = self.val['_M_impl']['_M_finish'] 551 return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'], 552 end['_M_cur'], self.buffer_size) 553 554 def display_hint (self): 555 return 'array' 556 557class StdDequeIteratorPrinter: 558 "Print std::deque::iterator" 559 560 def __init__(self, val): 561 self.val = val 562 563 def to_string(self): 564 return self.val['_M_cur'].dereference() 565 566class StdStringPrinter: 567 "Print a std::basic_string of some kind" 568 569 def __init__(self, val): 570 self.val = val 571 572 def to_string(self): 573 # Make sure &string works, too. 574 type = self.val.type 575 if type.code == gdb.TYPE_CODE_REF: 576 type = type.target () 577 578 # Calculate the length of the string so that to_string returns 579 # the string according to length, not according to first null 580 # encountered. 581 ptr = self.val ['_M_dataplus']['_M_p'] 582 realtype = type.unqualified ().strip_typedefs () 583 reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer () 584 header = ptr.cast(reptype) - 1 585 len = header.dereference ()['_M_length'] 586 if hasattr(ptr, "lazy_string"): 587 return ptr.lazy_string (length = len) 588 return ptr.string (length = len) 589 590 def display_hint (self): 591 return 'string' 592 593class Tr1HashtableIterator: 594 def __init__ (self, hash): 595 self.count = 0 596 self.n_buckets = hash['_M_element_count'] 597 if self.n_buckets == 0: 598 self.node = False 599 else: 600 self.bucket = hash['_M_buckets'] 601 self.node = self.bucket[0] 602 self.update () 603 604 def __iter__ (self): 605 return self 606 607 def update (self): 608 # If we advanced off the end of the chain, move to the next 609 # bucket. 610 while self.node == 0: 611 self.bucket = self.bucket + 1 612 self.node = self.bucket[0] 613 614 # If we advanced off the end of the bucket array, then 615 # we're done. 616 if self.count == self.n_buckets: 617 self.node = False 618 else: 619 self.count = self.count + 1 620 621 def next (self): 622 if not self.node: 623 raise StopIteration 624 result = self.node.dereference()['_M_v'] 625 self.node = self.node.dereference()['_M_next'] 626 self.update () 627 return result 628 629class Tr1UnorderedSetPrinter: 630 "Print a tr1::unordered_set" 631 632 def __init__ (self, typename, val): 633 self.typename = typename 634 self.val = val 635 636 def to_string (self): 637 return '%s with %d elements' % (self.typename, self.val['_M_element_count']) 638 639 @staticmethod 640 def format_count (i): 641 return '[%d]' % i 642 643 def children (self): 644 counter = itertools.imap (self.format_count, itertools.count()) 645 return itertools.izip (counter, Tr1HashtableIterator (self.val)) 646 647class Tr1UnorderedMapPrinter: 648 "Print a tr1::unordered_map" 649 650 def __init__ (self, typename, val): 651 self.typename = typename 652 self.val = val 653 654 def to_string (self): 655 return '%s with %d elements' % (self.typename, self.val['_M_element_count']) 656 657 @staticmethod 658 def flatten (list): 659 for elt in list: 660 for i in elt: 661 yield i 662 663 @staticmethod 664 def format_one (elt): 665 return (elt['first'], elt['second']) 666 667 @staticmethod 668 def format_count (i): 669 return '[%d]' % i 670 671 def children (self): 672 counter = itertools.imap (self.format_count, itertools.count()) 673 # Map over the hash table and flatten the result. 674 data = self.flatten (itertools.imap (self.format_one, Tr1HashtableIterator (self.val))) 675 # Zip the two iterators together. 676 return itertools.izip (counter, data) 677 678 def display_hint (self): 679 return 'map' 680 681def register_libstdcxx_printers (obj): 682 "Register libstdc++ pretty-printers with objfile Obj." 683 684 if obj == None: 685 obj = gdb 686 687 obj.pretty_printers.append (lookup_function) 688 689def lookup_function (val): 690 "Look-up and return a pretty-printer that can print val." 691 692 # Get the type. 693 type = val.type 694 695 # If it points to a reference, get the reference. 696 if type.code == gdb.TYPE_CODE_REF: 697 type = type.target () 698 699 # Get the unqualified type, stripped of typedefs. 700 type = type.unqualified ().strip_typedefs () 701 702 # Get the type name. 703 typename = type.tag 704 if typename == None: 705 return None 706 707 # Iterate over local dictionary of types to determine 708 # if a printer is registered for that type. Return an 709 # instantiation of the printer if found. 710 for function in pretty_printers_dict: 711 if function.search (typename): 712 return pretty_printers_dict[function] (val) 713 714 # Cannot find a pretty printer. Return None. 715 return None 716 717def build_libstdcxx_dictionary (): 718 # libstdc++ objects requiring pretty-printing. 719 # In order from: 720 # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html 721 pretty_printers_dict[re.compile('^std::basic_string<.*>$')] = lambda val: StdStringPrinter(val) 722 pretty_printers_dict[re.compile('^std::bitset<.*>$')] = lambda val: StdBitsetPrinter("std::bitset", val) 723 pretty_printers_dict[re.compile('^std::deque<.*>$')] = lambda val: StdDequePrinter("std::deque", val) 724 pretty_printers_dict[re.compile('^std::list<.*>$')] = lambda val: StdListPrinter("std::list", val) 725 pretty_printers_dict[re.compile('^std::map<.*>$')] = lambda val: StdMapPrinter("std::map", val) 726 pretty_printers_dict[re.compile('^std::multimap<.*>$')] = lambda val: StdMapPrinter("std::multimap", val) 727 pretty_printers_dict[re.compile('^std::multiset<.*>$')] = lambda val: StdSetPrinter("std::multiset", val) 728 pretty_printers_dict[re.compile('^std::priority_queue<.*>$')] = lambda val: StdStackOrQueuePrinter("std::priority_queue", val) 729 pretty_printers_dict[re.compile('^std::queue<.*>$')] = lambda val: StdStackOrQueuePrinter("std::queue", val) 730 pretty_printers_dict[re.compile('^std::tuple<.*>$')] = lambda val: StdTuplePrinter("std::tuple", val) 731 pretty_printers_dict[re.compile('^std::set<.*>$')] = lambda val: StdSetPrinter("std::set", val) 732 pretty_printers_dict[re.compile('^std::stack<.*>$')] = lambda val: StdStackOrQueuePrinter("std::stack", val) 733 pretty_printers_dict[re.compile('^std::unique_ptr<.*>$')] = UniquePointerPrinter 734 pretty_printers_dict[re.compile('^std::vector<.*>$')] = lambda val: StdVectorPrinter("std::vector", val) 735 # vector<bool> 736 737 # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG. 738 pretty_printers_dict[re.compile('^std::__debug::bitset<.*>$')] = lambda val: StdBitsetPrinter("std::__debug::bitset", val) 739 pretty_printers_dict[re.compile('^std::__debug::deque<.*>$')] = lambda val: StdDequePrinter("std::__debug::deque", val) 740 pretty_printers_dict[re.compile('^std::__debug::list<.*>$')] = lambda val: StdListPrinter("std::__debug::list", val) 741 pretty_printers_dict[re.compile('^std::__debug::map<.*>$')] = lambda val: StdMapPrinter("std::__debug::map", val) 742 pretty_printers_dict[re.compile('^std::__debug::multimap<.*>$')] = lambda val: StdMapPrinter("std::__debug::multimap", val) 743 pretty_printers_dict[re.compile('^std::__debug::multiset<.*>$')] = lambda val: StdSetPrinter("std::__debug::multiset", val) 744 pretty_printers_dict[re.compile('^std::__debug::priority_queue<.*>$')] = lambda val: StdStackOrQueuePrinter("std::__debug::priority_queue", val) 745 pretty_printers_dict[re.compile('^std::__debug::queue<.*>$')] = lambda val: StdStackOrQueuePrinter("std::__debug::queue", val) 746 pretty_printers_dict[re.compile('^std::__debug::set<.*>$')] = lambda val: StdSetPrinter("std::__debug::set", val) 747 pretty_printers_dict[re.compile('^std::__debug::stack<.*>$')] = lambda val: StdStackOrQueuePrinter("std::__debug::stack", val) 748 pretty_printers_dict[re.compile('^std::__debug::unique_ptr<.*>$')] = UniquePointerPrinter 749 pretty_printers_dict[re.compile('^std::__debug::vector<.*>$')] = lambda val: StdVectorPrinter("std::__debug::vector", val) 750 751 # These are the TR1 and C++0x printers. 752 # For array - the default GDB pretty-printer seems reasonable. 753 pretty_printers_dict[re.compile('^std::shared_ptr<.*>$')] = lambda val: StdPointerPrinter ('std::shared_ptr', val) 754 pretty_printers_dict[re.compile('^std::weak_ptr<.*>$')] = lambda val: StdPointerPrinter ('std::weak_ptr', val) 755 pretty_printers_dict[re.compile('^std::unordered_map<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::unordered_map', val) 756 pretty_printers_dict[re.compile('^std::unordered_set<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::unordered_set', val) 757 pretty_printers_dict[re.compile('^std::unordered_multimap<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::unordered_multimap', val) 758 pretty_printers_dict[re.compile('^std::unordered_multiset<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::unordered_multiset', val) 759 760 pretty_printers_dict[re.compile('^std::tr1::shared_ptr<.*>$')] = lambda val: StdPointerPrinter ('std::tr1::shared_ptr', val) 761 pretty_printers_dict[re.compile('^std::tr1::weak_ptr<.*>$')] = lambda val: StdPointerPrinter ('std::tr1::weak_ptr', val) 762 pretty_printers_dict[re.compile('^std::tr1::unordered_map<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::tr1::unordered_map', val) 763 pretty_printers_dict[re.compile('^std::tr1::unordered_set<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::tr1::unordered_set', val) 764 pretty_printers_dict[re.compile('^std::tr1::unordered_multimap<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::tr1::unordered_multimap', val) 765 pretty_printers_dict[re.compile('^std::tr1::unordered_multiset<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::tr1::unordered_multiset', val) 766 767 # These are the C++0x printer registrations for -D_GLIBCXX_DEBUG cases. 768 # The tr1 namespace printers do not seem to have any debug 769 # equivalents, so do no register them. 770 pretty_printers_dict[re.compile('^std::__debug::unordered_map<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::__debug::unordered_map', val) 771 pretty_printers_dict[re.compile('^std::__debug::unordered_set<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::__debug::unordered_set', val) 772 pretty_printers_dict[re.compile('^std::__debug::unordered_multimap<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::__debug::unordered_multimap', val) 773 pretty_printers_dict[re.compile('^std::__debug::unordered_multiset<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::__debug:unordered_multiset', val) 774 775 776 # Extensions. 777 pretty_printers_dict[re.compile('^__gnu_cxx::slist<.*>$')] = StdSlistPrinter 778 779 if True: 780 # These shouldn't be necessary, if GDB "print *i" worked. 781 # But it often doesn't, so here they are. 782 pretty_printers_dict[re.compile('^std::_List_iterator<.*>$')] = lambda val: StdListIteratorPrinter("std::_List_iterator",val) 783 pretty_printers_dict[re.compile('^std::_List_const_iterator<.*>$')] = lambda val: StdListIteratorPrinter("std::_List_const_iterator",val) 784 pretty_printers_dict[re.compile('^std::_Rb_tree_iterator<.*>$')] = lambda val: StdRbtreeIteratorPrinter(val) 785 pretty_printers_dict[re.compile('^std::_Rb_tree_const_iterator<.*>$')] = lambda val: StdRbtreeIteratorPrinter(val) 786 pretty_printers_dict[re.compile('^std::_Deque_iterator<.*>$')] = lambda val: StdDequeIteratorPrinter(val) 787 pretty_printers_dict[re.compile('^std::_Deque_const_iterator<.*>$')] = lambda val: StdDequeIteratorPrinter(val) 788 pretty_printers_dict[re.compile('^__gnu_cxx::__normal_iterator<.*>$')] = lambda val: StdVectorIteratorPrinter(val) 789 pretty_printers_dict[re.compile('^__gnu_cxx::_Slist_iterator<.*>$')] = lambda val: StdSlistIteratorPrinter(val) 790 791 # Debug (compiled with -D_GLIBCXX_DEBUG) printer registrations. 792 # The Rb_tree debug iterator when unwrapped from the encapsulating __gnu_debug::_Safe_iterator 793 # does not have the __norm namespace. Just use the existing printer registration for that. 794 pretty_printers_dict[re.compile('^__gnu_debug::_Safe_iterator<.*>$')] = lambda val: StdDebugIteratorPrinter(val) 795 pretty_printers_dict[re.compile('^std::__norm::_List_iterator<.*>$')] = lambda val: StdListIteratorPrinter ("std::__norm::_List_iterator",val) 796 pretty_printers_dict[re.compile('^std::__norm::_List_const_iterator<.*>$')] = lambda val: StdListIteratorPrinter ("std::__norm::_List_const_iterator",val) 797 pretty_printers_dict[re.compile('^std::__norm::_Deque_const_iterator<.*>$')] = lambda val: StdDequeIteratorPrinter(val) 798 pretty_printers_dict[re.compile('^std::__norm::_Deque_iterator<.*>$')] = lambda val: StdDequeIteratorPrinter(val) 799 800pretty_printers_dict = {} 801 802build_libstdcxx_dictionary () 803