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