1 // Debugging mode support code -*- C++ -*- 2 3 // Copyright (C) 2003-2015 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 #include <debug/debug.h> 26 #include <debug/safe_base.h> 27 #include <debug/safe_unordered_base.h> 28 #include <debug/safe_iterator.h> 29 #include <debug/safe_local_iterator.h> 30 #include <algorithm> 31 #include <cassert> 32 #include <cstring> 33 #include <cctype> 34 #include <cstdio> 35 #include <cstdlib> 36 #include <functional> 37 38 using namespace std; 39 40 namespace 41 { 42 /** Returns different instances of __mutex depending on the passed address 43 * in order to limit contention without breaking current library binary 44 * compatibility. */ 45 __gnu_cxx::__mutex& get_safe_base_mutex(void * __address)46 get_safe_base_mutex(void* __address) 47 { 48 const size_t mask = 0xf; 49 static __gnu_cxx::__mutex safe_base_mutex[mask + 1]; 50 const size_t index = _Hash_impl::hash(__address) & mask; 51 return safe_base_mutex[index]; 52 } 53 54 void swap_its(__gnu_debug::_Safe_sequence_base & __lhs,__gnu_debug::_Safe_iterator_base * & __lhs_its,__gnu_debug::_Safe_sequence_base & __rhs,__gnu_debug::_Safe_iterator_base * & __rhs_its)55 swap_its(__gnu_debug::_Safe_sequence_base& __lhs, 56 __gnu_debug::_Safe_iterator_base*& __lhs_its, 57 __gnu_debug::_Safe_sequence_base& __rhs, 58 __gnu_debug::_Safe_iterator_base*& __rhs_its) 59 { 60 swap(__lhs_its, __rhs_its); 61 __gnu_debug::_Safe_iterator_base* __iter; 62 for (__iter = __rhs_its; __iter; __iter = __iter->_M_next) 63 __iter->_M_sequence = &__rhs; 64 for (__iter = __lhs_its; __iter; __iter = __iter->_M_next) 65 __iter->_M_sequence = &__lhs; 66 } 67 68 void swap_seq(__gnu_debug::_Safe_sequence_base & __lhs,__gnu_debug::_Safe_sequence_base & __rhs)69 swap_seq(__gnu_debug::_Safe_sequence_base& __lhs, 70 __gnu_debug::_Safe_sequence_base& __rhs) 71 { 72 swap(__lhs._M_version, __rhs._M_version); 73 swap_its(__lhs, __lhs._M_iterators, 74 __rhs, __rhs._M_iterators); 75 swap_its(__lhs, __lhs._M_const_iterators, 76 __rhs, __rhs._M_const_iterators); 77 } 78 79 void swap_ucont(__gnu_debug::_Safe_unordered_container_base & __lhs,__gnu_debug::_Safe_unordered_container_base & __rhs)80 swap_ucont(__gnu_debug::_Safe_unordered_container_base& __lhs, 81 __gnu_debug::_Safe_unordered_container_base& __rhs) 82 { 83 swap_seq(__lhs, __rhs); 84 swap_its(__lhs, __lhs._M_local_iterators, 85 __rhs, __rhs._M_local_iterators); 86 swap_its(__lhs, __lhs._M_const_local_iterators, 87 __rhs, __rhs._M_const_local_iterators); 88 } 89 90 void detach_all(__gnu_debug::_Safe_iterator_base * __iter)91 detach_all(__gnu_debug::_Safe_iterator_base* __iter) 92 { 93 for (; __iter;) 94 { 95 __gnu_debug::_Safe_iterator_base* __old = __iter; 96 __iter = __iter->_M_next; 97 __old->_M_reset(); 98 } 99 } 100 } // anonymous namespace 101 102 namespace __gnu_debug 103 { 104 const char* _S_debug_messages[] = 105 { 106 // General Checks 107 "function requires a valid iterator range [%1.name;, %2.name;)", 108 "attempt to insert into container with a singular iterator", 109 "attempt to insert into container with an iterator" 110 " from a different container", 111 "attempt to erase from container with a %2.state; iterator", 112 "attempt to erase from container with an iterator" 113 " from a different container", 114 "attempt to subscript container with out-of-bounds index %2;," 115 " but container only holds %3; elements", 116 "attempt to access an element in an empty container", 117 "elements in iterator range [%1.name;, %2.name;)" 118 " are not partitioned by the value %3;", 119 "elements in iterator range [%1.name;, %2.name;)" 120 " are not partitioned by the predicate %3; and value %4;", 121 "elements in iterator range [%1.name;, %2.name;) are not sorted", 122 "elements in iterator range [%1.name;, %2.name;)" 123 " are not sorted according to the predicate %3;", 124 "elements in iterator range [%1.name;, %2.name;) do not form a heap", 125 "elements in iterator range [%1.name;, %2.name;)" 126 " do not form a heap with respect to the predicate %3;", 127 // std::bitset checks 128 "attempt to write through a singular bitset reference", 129 "attempt to read from a singular bitset reference", 130 "attempt to flip a singular bitset reference", 131 // std::list checks 132 "attempt to splice a list into itself", 133 "attempt to splice lists with unequal allocators", 134 "attempt to splice elements referenced by a %1.state; iterator", 135 "attempt to splice an iterator from a different container", 136 "splice destination %1.name;" 137 " occurs within source range [%2.name;, %3.name;)", 138 // iterator checks 139 "attempt to initialize an iterator that will immediately become singular", 140 "attempt to copy-construct an iterator from a singular iterator", 141 "attempt to construct a constant iterator" 142 " from a singular mutable iterator", 143 "attempt to copy from a singular iterator", 144 "attempt to dereference a %1.state; iterator", 145 "attempt to increment a %1.state; iterator", 146 "attempt to decrement a %1.state; iterator", 147 "attempt to subscript a %1.state; iterator %2; step from" 148 " its current position, which falls outside its dereferenceable range", 149 "attempt to advance a %1.state; iterator %2; steps," 150 " which falls outside its valid range", 151 "attempt to retreat a %1.state; iterator %2; steps," 152 " which falls outside its valid range", 153 "attempt to compare a %1.state; iterator to a %2.state; iterator", 154 "attempt to compare iterators from different sequences", 155 "attempt to order a %1.state; iterator to a %2.state; iterator", 156 "attempt to order iterators from different sequences", 157 "attempt to compute the difference between a %1.state;" 158 " iterator to a %2.state; iterator", 159 "attempt to compute the different between two iterators" 160 " from different sequences", 161 // istream_iterator 162 "attempt to dereference an end-of-stream istream_iterator", 163 "attempt to increment an end-of-stream istream_iterator", 164 // ostream_iterator 165 "attempt to output via an ostream_iterator with no associated stream", 166 // istreambuf_iterator 167 "attempt to dereference an end-of-stream istreambuf_iterator" 168 " (this is a GNU extension)", 169 "attempt to increment an end-of-stream istreambuf_iterator", 170 // std::forward_list 171 "attempt to insert into container after an end iterator", 172 "attempt to erase from container after a %2.state; iterator not followed" 173 " by a dereferenceable one", 174 "function requires a valid iterator range (%2.name;, %3.name;)" 175 ", \"%2.name;\" shall be before and not equal to \"%3.name;\"", 176 // std::unordered_container::local_iterator 177 "attempt to compare local iterators from different unordered container" 178 " buckets", 179 "function requires a non-empty iterator range [%1.name;, %2.name;)", 180 "attempt to self move assign", 181 "attempt to access container with out-of-bounds bucket index %2;," 182 " container only holds %3; buckets", 183 "load factor shall be positive", 184 "allocators must be equal", 185 "attempt to insert with an iterator range [%1.name;, %2.name;) from this container" 186 }; 187 188 void 189 _Safe_sequence_base:: _M_detach_all()190 _M_detach_all() 191 { 192 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 193 detach_all(_M_iterators); 194 _M_iterators = 0; 195 196 detach_all(_M_const_iterators); 197 _M_const_iterators = 0; 198 } 199 200 void 201 _Safe_sequence_base:: _M_detach_singular()202 _M_detach_singular() 203 { 204 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 205 for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 206 { 207 _Safe_iterator_base* __old = __iter; 208 __iter = __iter->_M_next; 209 if (__old->_M_singular()) 210 __old->_M_detach_single(); 211 } 212 213 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 214 { 215 _Safe_iterator_base* __old = __iter2; 216 __iter2 = __iter2->_M_next; 217 if (__old->_M_singular()) 218 __old->_M_detach_single(); 219 } 220 } 221 222 void 223 _Safe_sequence_base:: _M_revalidate_singular()224 _M_revalidate_singular() 225 { 226 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 227 for (_Safe_iterator_base* __iter = _M_iterators; __iter; 228 __iter = __iter->_M_next) 229 __iter->_M_version = _M_version; 230 231 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; 232 __iter2 = __iter2->_M_next) 233 __iter2->_M_version = _M_version; 234 } 235 236 void 237 _Safe_sequence_base:: _M_swap(_Safe_sequence_base & __x)238 _M_swap(_Safe_sequence_base& __x) noexcept 239 { 240 // We need to lock both sequences to swap 241 using namespace __gnu_cxx; 242 __mutex *__this_mutex = &_M_get_mutex(); 243 __mutex *__x_mutex = &__x._M_get_mutex(); 244 if (__this_mutex == __x_mutex) 245 { 246 __scoped_lock __lock(*__this_mutex); 247 swap_seq(*this, __x); 248 } 249 else 250 { 251 __scoped_lock __l1(__this_mutex < __x_mutex 252 ? *__this_mutex : *__x_mutex); 253 __scoped_lock __l2(__this_mutex < __x_mutex 254 ? *__x_mutex : *__this_mutex); 255 swap_seq(*this, __x); 256 } 257 } 258 259 __gnu_cxx::__mutex& 260 _Safe_sequence_base:: _M_get_mutex()261 _M_get_mutex() throw () 262 { return get_safe_base_mutex(this); } 263 264 void 265 _Safe_sequence_base:: _M_attach(_Safe_iterator_base * __it,bool __constant)266 _M_attach(_Safe_iterator_base* __it, bool __constant) 267 { 268 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 269 _M_attach_single(__it, __constant); 270 } 271 272 void 273 _Safe_sequence_base:: _M_attach_single(_Safe_iterator_base * __it,bool __constant)274 _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw () 275 { 276 _Safe_iterator_base*& __its = 277 __constant ? _M_const_iterators : _M_iterators; 278 __it->_M_next = __its; 279 if (__it->_M_next) 280 __it->_M_next->_M_prior = __it; 281 __its = __it; 282 } 283 284 void 285 _Safe_sequence_base:: _M_detach(_Safe_iterator_base * __it)286 _M_detach(_Safe_iterator_base* __it) 287 { 288 // Remove __it from this sequence's list 289 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 290 _M_detach_single(__it); 291 } 292 293 void 294 _Safe_sequence_base:: _M_detach_single(_Safe_iterator_base * __it)295 _M_detach_single(_Safe_iterator_base* __it) throw () 296 { 297 // Remove __it from this sequence's list 298 __it->_M_unlink(); 299 if (_M_const_iterators == __it) 300 _M_const_iterators = __it->_M_next; 301 if (_M_iterators == __it) 302 _M_iterators = __it->_M_next; 303 } 304 305 void 306 _Safe_iterator_base:: _M_attach(_Safe_sequence_base * __seq,bool __constant)307 _M_attach(_Safe_sequence_base* __seq, bool __constant) 308 { 309 _M_detach(); 310 311 // Attach to the new sequence (if there is one) 312 if (__seq) 313 { 314 _M_sequence = __seq; 315 _M_version = _M_sequence->_M_version; 316 _M_sequence->_M_attach(this, __constant); 317 } 318 } 319 320 void 321 _Safe_iterator_base:: _M_attach_single(_Safe_sequence_base * __seq,bool __constant)322 _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw () 323 { 324 _M_detach_single(); 325 326 // Attach to the new sequence (if there is one) 327 if (__seq) 328 { 329 _M_sequence = __seq; 330 _M_version = _M_sequence->_M_version; 331 _M_sequence->_M_attach_single(this, __constant); 332 } 333 } 334 335 void 336 _Safe_iterator_base:: _M_detach()337 _M_detach() 338 { 339 if (_M_sequence) 340 _M_sequence->_M_detach(this); 341 342 _M_reset(); 343 } 344 345 void 346 _Safe_iterator_base:: _M_detach_single()347 _M_detach_single() throw () 348 { 349 if (_M_sequence) 350 _M_sequence->_M_detach_single(this); 351 352 _M_reset(); 353 } 354 355 void 356 _Safe_iterator_base:: _M_reset()357 _M_reset() throw () 358 { 359 _M_sequence = 0; 360 _M_version = 0; 361 _M_prior = 0; 362 _M_next = 0; 363 } 364 365 bool 366 _Safe_iterator_base:: _M_singular() const367 _M_singular() const throw () 368 { return !_M_sequence || _M_version != _M_sequence->_M_version; } 369 370 bool 371 _Safe_iterator_base:: _M_can_compare(const _Safe_iterator_base & __x) const372 _M_can_compare(const _Safe_iterator_base& __x) const throw () 373 { 374 return (!_M_singular() 375 && !__x._M_singular() && _M_sequence == __x._M_sequence); 376 } 377 378 __gnu_cxx::__mutex& 379 _Safe_iterator_base:: _M_get_mutex()380 _M_get_mutex() throw () 381 { return get_safe_base_mutex(_M_sequence); } 382 383 _Safe_unordered_container_base* 384 _Safe_local_iterator_base:: _M_get_container() const385 _M_get_container() const noexcept 386 { return static_cast<_Safe_unordered_container_base*>(_M_sequence); } 387 388 void 389 _Safe_local_iterator_base:: _M_attach(_Safe_sequence_base * __cont,bool __constant)390 _M_attach(_Safe_sequence_base* __cont, bool __constant) 391 { 392 _M_detach(); 393 394 // Attach to the new container (if there is one) 395 if (__cont) 396 { 397 _M_sequence = __cont; 398 _M_version = _M_sequence->_M_version; 399 _M_get_container()->_M_attach_local(this, __constant); 400 } 401 } 402 403 void 404 _Safe_local_iterator_base:: _M_attach_single(_Safe_sequence_base * __cont,bool __constant)405 _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw () 406 { 407 _M_detach_single(); 408 409 // Attach to the new container (if there is one) 410 if (__cont) 411 { 412 _M_sequence = __cont; 413 _M_version = _M_sequence->_M_version; 414 _M_get_container()->_M_attach_local_single(this, __constant); 415 } 416 } 417 418 void 419 _Safe_local_iterator_base:: _M_detach()420 _M_detach() 421 { 422 if (_M_sequence) 423 _M_get_container()->_M_detach_local(this); 424 425 _M_reset(); 426 } 427 428 void 429 _Safe_local_iterator_base:: _M_detach_single()430 _M_detach_single() throw () 431 { 432 if (_M_sequence) 433 _M_get_container()->_M_detach_local_single(this); 434 435 _M_reset(); 436 } 437 438 void 439 _Safe_unordered_container_base:: _M_detach_all()440 _M_detach_all() 441 { 442 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 443 detach_all(_M_iterators); 444 _M_iterators = 0; 445 446 detach_all(_M_const_iterators); 447 _M_const_iterators = 0; 448 449 detach_all(_M_local_iterators); 450 _M_local_iterators = 0; 451 452 detach_all(_M_const_local_iterators); 453 _M_const_local_iterators = 0; 454 } 455 456 void 457 _Safe_unordered_container_base:: _M_swap(_Safe_unordered_container_base & __x)458 _M_swap(_Safe_unordered_container_base& __x) noexcept 459 { 460 // We need to lock both containers to swap 461 using namespace __gnu_cxx; 462 __mutex *__this_mutex = &_M_get_mutex(); 463 __mutex *__x_mutex = &__x._M_get_mutex(); 464 if (__this_mutex == __x_mutex) 465 { 466 __scoped_lock __lock(*__this_mutex); 467 swap_ucont(*this, __x); 468 } 469 else 470 { 471 __scoped_lock __l1(__this_mutex < __x_mutex 472 ? *__this_mutex : *__x_mutex); 473 __scoped_lock __l2(__this_mutex < __x_mutex 474 ? *__x_mutex : *__this_mutex); 475 swap_ucont(*this, __x); 476 } 477 } 478 479 void 480 _Safe_unordered_container_base:: _M_attach_local(_Safe_iterator_base * __it,bool __constant)481 _M_attach_local(_Safe_iterator_base* __it, bool __constant) 482 { 483 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 484 _M_attach_local_single(__it, __constant); 485 } 486 487 void 488 _Safe_unordered_container_base:: _M_attach_local_single(_Safe_iterator_base * __it,bool __constant)489 _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw () 490 { 491 _Safe_iterator_base*& __its = 492 __constant ? _M_const_local_iterators : _M_local_iterators; 493 __it->_M_next = __its; 494 if (__it->_M_next) 495 __it->_M_next->_M_prior = __it; 496 __its = __it; 497 } 498 499 void 500 _Safe_unordered_container_base:: _M_detach_local(_Safe_iterator_base * __it)501 _M_detach_local(_Safe_iterator_base* __it) 502 { 503 // Remove __it from this container's list 504 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 505 _M_detach_local_single(__it); 506 } 507 508 void 509 _Safe_unordered_container_base:: _M_detach_local_single(_Safe_iterator_base * __it)510 _M_detach_local_single(_Safe_iterator_base* __it) throw () 511 { 512 // Remove __it from this container's list 513 __it->_M_unlink(); 514 if (_M_const_local_iterators == __it) 515 _M_const_local_iterators = __it->_M_next; 516 if (_M_local_iterators == __it) 517 _M_local_iterators = __it->_M_next; 518 } 519 520 void 521 _Error_formatter::_Parameter:: _M_print_field(const _Error_formatter * __formatter,const char * __name) const522 _M_print_field(const _Error_formatter* __formatter, const char* __name) const 523 { 524 assert(this->_M_kind != _Parameter::__unused_param); 525 const int __bufsize = 64; 526 char __buf[__bufsize]; 527 528 if (_M_kind == __iterator) 529 { 530 if (strcmp(__name, "name") == 0) 531 { 532 assert(_M_variant._M_iterator._M_name); 533 __formatter->_M_print_word(_M_variant._M_iterator._M_name); 534 } 535 else if (strcmp(__name, "address") == 0) 536 { 537 __formatter->_M_format_word(__buf, __bufsize, "%p", 538 _M_variant._M_iterator._M_address); 539 __formatter->_M_print_word(__buf); 540 } 541 else if (strcmp(__name, "type") == 0) 542 { 543 if (!_M_variant._M_iterator._M_type) 544 __formatter->_M_print_word("<unknown type>"); 545 else 546 // TBD: demangle! 547 __formatter->_M_print_word(_M_variant._M_iterator. 548 _M_type->name()); 549 } 550 else if (strcmp(__name, "constness") == 0) 551 { 552 static const char* __constness_names[__last_constness] = 553 { 554 "<unknown>", 555 "constant", 556 "mutable" 557 }; 558 __formatter->_M_print_word(__constness_names[_M_variant. 559 _M_iterator. 560 _M_constness]); 561 } 562 else if (strcmp(__name, "state") == 0) 563 { 564 static const char* __state_names[__last_state] = 565 { 566 "<unknown>", 567 "singular", 568 "dereferenceable (start-of-sequence)", 569 "dereferenceable", 570 "past-the-end", 571 "before-begin" 572 }; 573 __formatter->_M_print_word(__state_names[_M_variant. 574 _M_iterator._M_state]); 575 } 576 else if (strcmp(__name, "sequence") == 0) 577 { 578 assert(_M_variant._M_iterator._M_sequence); 579 __formatter->_M_format_word(__buf, __bufsize, "%p", 580 _M_variant._M_iterator._M_sequence); 581 __formatter->_M_print_word(__buf); 582 } 583 else if (strcmp(__name, "seq_type") == 0) 584 { 585 if (!_M_variant._M_iterator._M_seq_type) 586 __formatter->_M_print_word("<unknown seq_type>"); 587 else 588 // TBD: demangle! 589 __formatter->_M_print_word(_M_variant._M_iterator. 590 _M_seq_type->name()); 591 } 592 else 593 assert(false); 594 } 595 else if (_M_kind == __sequence) 596 { 597 if (strcmp(__name, "name") == 0) 598 { 599 assert(_M_variant._M_sequence._M_name); 600 __formatter->_M_print_word(_M_variant._M_sequence._M_name); 601 } 602 else if (strcmp(__name, "address") == 0) 603 { 604 assert(_M_variant._M_sequence._M_address); 605 __formatter->_M_format_word(__buf, __bufsize, "%p", 606 _M_variant._M_sequence._M_address); 607 __formatter->_M_print_word(__buf); 608 } 609 else if (strcmp(__name, "type") == 0) 610 { 611 if (!_M_variant._M_sequence._M_type) 612 __formatter->_M_print_word("<unknown type>"); 613 else 614 // TBD: demangle! 615 __formatter->_M_print_word(_M_variant._M_sequence. 616 _M_type->name()); 617 } 618 else 619 assert(false); 620 } 621 else if (_M_kind == __integer) 622 { 623 if (strcmp(__name, "name") == 0) 624 { 625 assert(_M_variant._M_integer._M_name); 626 __formatter->_M_print_word(_M_variant._M_integer._M_name); 627 } 628 else 629 assert(false); 630 } 631 else if (_M_kind == __string) 632 { 633 if (strcmp(__name, "name") == 0) 634 { 635 assert(_M_variant._M_string._M_name); 636 __formatter->_M_print_word(_M_variant._M_string._M_name); 637 } 638 else 639 assert(false); 640 } 641 else 642 { 643 assert(false); 644 } 645 } 646 647 void 648 _Error_formatter::_Parameter:: _M_print_description(const _Error_formatter * __formatter) const649 _M_print_description(const _Error_formatter* __formatter) const 650 { 651 const int __bufsize = 128; 652 char __buf[__bufsize]; 653 654 if (_M_kind == __iterator) 655 { 656 __formatter->_M_print_word("iterator "); 657 if (_M_variant._M_iterator._M_name) 658 { 659 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 660 _M_variant._M_iterator._M_name); 661 __formatter->_M_print_word(__buf); 662 } 663 664 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 665 _M_variant._M_iterator._M_address); 666 __formatter->_M_print_word(__buf); 667 if (_M_variant._M_iterator._M_type) 668 { 669 __formatter->_M_print_word("type = "); 670 _M_print_field(__formatter, "type"); 671 672 if (_M_variant._M_iterator._M_constness != __unknown_constness) 673 { 674 __formatter->_M_print_word(" ("); 675 _M_print_field(__formatter, "constness"); 676 __formatter->_M_print_word(" iterator)"); 677 } 678 __formatter->_M_print_word(";\n"); 679 } 680 681 if (_M_variant._M_iterator._M_state != __unknown_state) 682 { 683 __formatter->_M_print_word(" state = "); 684 _M_print_field(__formatter, "state"); 685 __formatter->_M_print_word(";\n"); 686 } 687 688 if (_M_variant._M_iterator._M_sequence) 689 { 690 __formatter->_M_print_word(" references sequence "); 691 if (_M_variant._M_iterator._M_seq_type) 692 { 693 __formatter->_M_print_word("with type `"); 694 _M_print_field(__formatter, "seq_type"); 695 __formatter->_M_print_word("' "); 696 } 697 698 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n", 699 _M_variant._M_iterator._M_sequence); 700 __formatter->_M_print_word(__buf); 701 } 702 __formatter->_M_print_word("}\n"); 703 } 704 else if (_M_kind == __sequence) 705 { 706 __formatter->_M_print_word("sequence "); 707 if (_M_variant._M_sequence._M_name) 708 { 709 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 710 _M_variant._M_sequence._M_name); 711 __formatter->_M_print_word(__buf); 712 } 713 714 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 715 _M_variant._M_sequence._M_address); 716 __formatter->_M_print_word(__buf); 717 718 if (_M_variant._M_sequence._M_type) 719 { 720 __formatter->_M_print_word(" type = "); 721 _M_print_field(__formatter, "type"); 722 __formatter->_M_print_word(";\n"); 723 } 724 __formatter->_M_print_word("}\n"); 725 } 726 } 727 728 const _Error_formatter& _M_message(_Debug_msg_id __id) const729 _Error_formatter::_M_message(_Debug_msg_id __id) const throw () 730 { return this->_M_message(_S_debug_messages[__id]); } 731 732 void _M_error() const733 _Error_formatter::_M_error() const 734 { 735 const int __bufsize = 128; 736 char __buf[__bufsize]; 737 738 // Emit file & line number information 739 _M_column = 1; 740 _M_wordwrap = false; 741 if (_M_file) 742 { 743 _M_format_word(__buf, __bufsize, "%s:", _M_file); 744 _M_print_word(__buf); 745 _M_column += strlen(__buf); 746 } 747 748 if (_M_line > 0) 749 { 750 _M_format_word(__buf, __bufsize, "%u:", _M_line); 751 _M_print_word(__buf); 752 _M_column += strlen(__buf); 753 } 754 755 if (_M_max_length) 756 _M_wordwrap = true; 757 _M_print_word("error: "); 758 759 // Print the error message 760 assert(_M_text); 761 _M_print_string(_M_text); 762 _M_print_word(".\n"); 763 764 // Emit descriptions of the objects involved in the operation 765 _M_wordwrap = false; 766 bool __has_noninteger_parameters = false; 767 for (unsigned int __i = 0; __i < _M_num_parameters; ++__i) 768 { 769 if (_M_parameters[__i]._M_kind == _Parameter::__iterator 770 || _M_parameters[__i]._M_kind == _Parameter::__sequence) 771 { 772 if (!__has_noninteger_parameters) 773 { 774 _M_first_line = true; 775 _M_print_word("\nObjects involved in the operation:\n"); 776 __has_noninteger_parameters = true; 777 } 778 _M_parameters[__i]._M_print_description(this); 779 } 780 } 781 782 abort(); 783 } 784 785 template<typename _Tp> 786 void _M_format_word(char * __buf,int __n,const char * __fmt,_Tp __s) const787 _Error_formatter::_M_format_word(char* __buf, 788 int __n __attribute__ ((__unused__)), 789 const char* __fmt, _Tp __s) const throw () 790 { 791 #ifdef _GLIBCXX_USE_C99 792 std::snprintf(__buf, __n, __fmt, __s); 793 #else 794 std::sprintf(__buf, __fmt, __s); 795 #endif 796 } 797 798 799 void _M_print_word(const char * __word) const800 _Error_formatter::_M_print_word(const char* __word) const 801 { 802 if (!_M_wordwrap) 803 { 804 fprintf(stderr, "%s", __word); 805 return; 806 } 807 808 size_t __length = strlen(__word); 809 if (__length == 0) 810 return; 811 812 size_t __visual_length 813 = __word[__length - 1] == '\n' ? __length - 1 : __length; 814 if (__visual_length == 0 815 || (_M_column + __visual_length < _M_max_length) 816 || (__visual_length >= _M_max_length && _M_column == 1)) 817 { 818 // If this isn't the first line, indent 819 if (_M_column == 1 && !_M_first_line) 820 { 821 char __spacing[_M_indent + 1]; 822 for (int i = 0; i < _M_indent; ++i) 823 __spacing[i] = ' '; 824 __spacing[_M_indent] = '\0'; 825 fprintf(stderr, "%s", __spacing); 826 _M_column += _M_indent; 827 } 828 829 fprintf(stderr, "%s", __word); 830 831 if (__word[__length - 1] == '\n') 832 { 833 _M_first_line = false; 834 _M_column = 1; 835 } 836 else 837 _M_column += __length; 838 } 839 else 840 { 841 _M_print_word("\n"); 842 _M_print_word(__word); 843 } 844 } 845 846 void 847 _Error_formatter:: _M_print_string(const char * __string) const848 _M_print_string(const char* __string) const 849 { 850 const char* __start = __string; 851 const char* __finish = __start; 852 const int __bufsize = 128; 853 char __buf[__bufsize]; 854 855 while (*__start) 856 { 857 if (*__start != '%') 858 { 859 // [__start, __finish) denotes the next word 860 __finish = __start; 861 while (isalnum(*__finish)) 862 ++__finish; 863 if (__start == __finish) 864 ++__finish; 865 if (isspace(*__finish)) 866 ++__finish; 867 868 const ptrdiff_t __len = __finish - __start; 869 assert(__len < __bufsize); 870 memcpy(__buf, __start, __len); 871 __buf[__len] = '\0'; 872 _M_print_word(__buf); 873 __start = __finish; 874 875 // Skip extra whitespace 876 while (*__start == ' ') 877 ++__start; 878 879 continue; 880 } 881 882 ++__start; 883 assert(*__start); 884 if (*__start == '%') 885 { 886 _M_print_word("%"); 887 ++__start; 888 continue; 889 } 890 891 // Get the parameter number 892 assert(*__start >= '1' && *__start <= '9'); 893 size_t __param = *__start - '0'; 894 --__param; 895 assert(__param < _M_num_parameters); 896 897 // '.' separates the parameter number from the field 898 // name, if there is one. 899 ++__start; 900 if (*__start != '.') 901 { 902 assert(*__start == ';'); 903 ++__start; 904 __buf[0] = '\0'; 905 if (_M_parameters[__param]._M_kind == _Parameter::__integer) 906 { 907 _M_format_word(__buf, __bufsize, "%ld", 908 _M_parameters[__param]._M_variant._M_integer._M_value); 909 _M_print_word(__buf); 910 } 911 else if (_M_parameters[__param]._M_kind == _Parameter::__string) 912 _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value); 913 continue; 914 } 915 916 // Extract the field name we want 917 enum { __max_field_len = 16 }; 918 char __field[__max_field_len]; 919 int __field_idx = 0; 920 ++__start; 921 while (*__start != ';') 922 { 923 assert(*__start); 924 assert(__field_idx < __max_field_len-1); 925 __field[__field_idx++] = *__start++; 926 } 927 ++__start; 928 __field[__field_idx] = 0; 929 930 _M_parameters[__param]._M_print_field(this, __field); 931 } 932 } 933 934 void _M_get_max_length() const935 _Error_formatter::_M_get_max_length() const throw () 936 { 937 const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH"); 938 if (__nptr) 939 { 940 char* __endptr; 941 const unsigned long __ret = std::strtoul(__nptr, &__endptr, 0); 942 if (*__nptr != '\0' && *__endptr == '\0') 943 _M_max_length = __ret; 944 } 945 } 946 947 // Instantiations. 948 template 949 void 950 _Error_formatter::_M_format_word(char*, int, const char*, 951 const void*) const; 952 953 template 954 void 955 _Error_formatter::_M_format_word(char*, int, const char*, long) const; 956 957 template 958 void 959 _Error_formatter::_M_format_word(char*, int, const char*, 960 std::size_t) const; 961 962 template 963 void 964 _Error_formatter::_M_format_word(char*, int, const char*, 965 const char*) const; 966 } // namespace __gnu_debug 967