1 // Debugging mode support code -*- C++ -*- 2 3 // Copyright (C) 2003-2013 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_sequence.h> 27 #include <debug/safe_unordered_container.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& 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 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 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 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 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 }; 186 187 void 188 _Safe_sequence_base:: 189 _M_detach_all() 190 { 191 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 192 detach_all(_M_iterators); 193 _M_iterators = 0; 194 195 detach_all(_M_const_iterators); 196 _M_const_iterators = 0; 197 } 198 199 void 200 _Safe_sequence_base:: 201 _M_detach_singular() 202 { 203 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 204 for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 205 { 206 _Safe_iterator_base* __old = __iter; 207 __iter = __iter->_M_next; 208 if (__old->_M_singular()) 209 __old->_M_detach_single(); 210 } 211 212 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 213 { 214 _Safe_iterator_base* __old = __iter2; 215 __iter2 = __iter2->_M_next; 216 if (__old->_M_singular()) 217 __old->_M_detach_single(); 218 } 219 } 220 221 void 222 _Safe_sequence_base:: 223 _M_revalidate_singular() 224 { 225 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 226 for (_Safe_iterator_base* __iter = _M_iterators; __iter; 227 __iter = __iter->_M_next) 228 __iter->_M_version = _M_version; 229 230 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; 231 __iter2 = __iter2->_M_next) 232 __iter2->_M_version = _M_version; 233 } 234 235 void 236 _Safe_sequence_base:: 237 _M_swap(_Safe_sequence_base& __x) 238 { 239 // We need to lock both sequences to swap 240 using namespace __gnu_cxx; 241 __mutex *__this_mutex = &_M_get_mutex(); 242 __mutex *__x_mutex = &__x._M_get_mutex(); 243 if (__this_mutex == __x_mutex) 244 { 245 __scoped_lock __lock(*__this_mutex); 246 swap_seq(*this, __x); 247 } 248 else 249 { 250 __scoped_lock __l1(__this_mutex < __x_mutex 251 ? *__this_mutex : *__x_mutex); 252 __scoped_lock __l2(__this_mutex < __x_mutex 253 ? *__x_mutex : *__this_mutex); 254 swap_seq(*this, __x); 255 } 256 } 257 258 __gnu_cxx::__mutex& 259 _Safe_sequence_base:: 260 _M_get_mutex() throw () 261 { return get_safe_base_mutex(this); } 262 263 void 264 _Safe_sequence_base:: 265 _M_attach(_Safe_iterator_base* __it, bool __constant) 266 { 267 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 268 _M_attach_single(__it, __constant); 269 } 270 271 void 272 _Safe_sequence_base:: 273 _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw () 274 { 275 _Safe_iterator_base*& __its = 276 __constant ? _M_const_iterators : _M_iterators; 277 __it->_M_next = __its; 278 if (__it->_M_next) 279 __it->_M_next->_M_prior = __it; 280 __its = __it; 281 } 282 283 void 284 _Safe_sequence_base:: 285 _M_detach(_Safe_iterator_base* __it) 286 { 287 // Remove __it from this sequence's list 288 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 289 _M_detach_single(__it); 290 } 291 292 void 293 _Safe_sequence_base:: 294 _M_detach_single(_Safe_iterator_base* __it) throw () 295 { 296 // Remove __it from this sequence's list 297 __it->_M_unlink(); 298 if (_M_const_iterators == __it) 299 _M_const_iterators = __it->_M_next; 300 if (_M_iterators == __it) 301 _M_iterators = __it->_M_next; 302 } 303 304 void 305 _Safe_iterator_base:: 306 _M_attach(_Safe_sequence_base* __seq, bool __constant) 307 { 308 _M_detach(); 309 310 // Attach to the new sequence (if there is one) 311 if (__seq) 312 { 313 _M_sequence = __seq; 314 _M_version = _M_sequence->_M_version; 315 _M_sequence->_M_attach(this, __constant); 316 } 317 } 318 319 void 320 _Safe_iterator_base:: 321 _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw () 322 { 323 _M_detach_single(); 324 325 // Attach to the new sequence (if there is one) 326 if (__seq) 327 { 328 _M_sequence = __seq; 329 _M_version = _M_sequence->_M_version; 330 _M_sequence->_M_attach_single(this, __constant); 331 } 332 } 333 334 void 335 _Safe_iterator_base:: 336 _M_detach() 337 { 338 if (_M_sequence) 339 _M_sequence->_M_detach(this); 340 341 _M_reset(); 342 } 343 344 void 345 _Safe_iterator_base:: 346 _M_detach_single() throw () 347 { 348 if (_M_sequence) 349 _M_sequence->_M_detach_single(this); 350 351 _M_reset(); 352 } 353 354 void 355 _Safe_iterator_base:: 356 _M_reset() throw () 357 { 358 _M_sequence = 0; 359 _M_version = 0; 360 _M_prior = 0; 361 _M_next = 0; 362 } 363 364 bool 365 _Safe_iterator_base:: 366 _M_singular() const throw () 367 { return !_M_sequence || _M_version != _M_sequence->_M_version; } 368 369 bool 370 _Safe_iterator_base:: 371 _M_can_compare(const _Safe_iterator_base& __x) const throw () 372 { 373 return (!_M_singular() 374 && !__x._M_singular() && _M_sequence == __x._M_sequence); 375 } 376 377 __gnu_cxx::__mutex& 378 _Safe_iterator_base:: 379 _M_get_mutex() throw () 380 { return get_safe_base_mutex(_M_sequence); } 381 382 _Safe_unordered_container_base* 383 _Safe_local_iterator_base:: 384 _M_get_container() const _GLIBCXX_NOEXCEPT 385 { return static_cast<_Safe_unordered_container_base*>(_M_sequence); } 386 387 void 388 _Safe_local_iterator_base:: 389 _M_attach(_Safe_sequence_base* __cont, bool __constant) 390 { 391 _M_detach(); 392 393 // Attach to the new container (if there is one) 394 if (__cont) 395 { 396 _M_sequence = __cont; 397 _M_version = _M_sequence->_M_version; 398 _M_get_container()->_M_attach_local(this, __constant); 399 } 400 } 401 402 void 403 _Safe_local_iterator_base:: 404 _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw () 405 { 406 _M_detach_single(); 407 408 // Attach to the new container (if there is one) 409 if (__cont) 410 { 411 _M_sequence = __cont; 412 _M_version = _M_sequence->_M_version; 413 _M_get_container()->_M_attach_local_single(this, __constant); 414 } 415 } 416 417 void 418 _Safe_local_iterator_base:: 419 _M_detach() 420 { 421 if (_M_sequence) 422 _M_get_container()->_M_detach_local(this); 423 424 _M_reset(); 425 } 426 427 void 428 _Safe_local_iterator_base:: 429 _M_detach_single() throw () 430 { 431 if (_M_sequence) 432 _M_get_container()->_M_detach_local_single(this); 433 434 _M_reset(); 435 } 436 437 void 438 _Safe_unordered_container_base:: 439 _M_detach_all() 440 { 441 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 442 detach_all(_M_iterators); 443 _M_iterators = 0; 444 445 detach_all(_M_const_iterators); 446 _M_const_iterators = 0; 447 448 detach_all(_M_local_iterators); 449 _M_local_iterators = 0; 450 451 detach_all(_M_const_local_iterators); 452 _M_const_local_iterators = 0; 453 } 454 455 void 456 _Safe_unordered_container_base:: 457 _M_swap(_Safe_unordered_container_base& __x) 458 { 459 // We need to lock both containers to swap 460 using namespace __gnu_cxx; 461 __mutex *__this_mutex = &_M_get_mutex(); 462 __mutex *__x_mutex = &__x._M_get_mutex(); 463 if (__this_mutex == __x_mutex) 464 { 465 __scoped_lock __lock(*__this_mutex); 466 swap_ucont(*this, __x); 467 } 468 else 469 { 470 __scoped_lock __l1(__this_mutex < __x_mutex 471 ? *__this_mutex : *__x_mutex); 472 __scoped_lock __l2(__this_mutex < __x_mutex 473 ? *__x_mutex : *__this_mutex); 474 swap_ucont(*this, __x); 475 } 476 } 477 478 void 479 _Safe_unordered_container_base:: 480 _M_attach_local(_Safe_iterator_base* __it, bool __constant) 481 { 482 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 483 _M_attach_local_single(__it, __constant); 484 } 485 486 void 487 _Safe_unordered_container_base:: 488 _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw () 489 { 490 _Safe_iterator_base*& __its = 491 __constant ? _M_const_local_iterators : _M_local_iterators; 492 __it->_M_next = __its; 493 if (__it->_M_next) 494 __it->_M_next->_M_prior = __it; 495 __its = __it; 496 } 497 498 void 499 _Safe_unordered_container_base:: 500 _M_detach_local(_Safe_iterator_base* __it) 501 { 502 // Remove __it from this container's list 503 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 504 _M_detach_local_single(__it); 505 } 506 507 void 508 _Safe_unordered_container_base:: 509 _M_detach_local_single(_Safe_iterator_base* __it) throw () 510 { 511 // Remove __it from this container's list 512 __it->_M_unlink(); 513 if (_M_const_local_iterators == __it) 514 _M_const_local_iterators = __it->_M_next; 515 if (_M_local_iterators == __it) 516 _M_local_iterators = __it->_M_next; 517 } 518 519 void 520 _Error_formatter::_Parameter:: 521 _M_print_field(const _Error_formatter* __formatter, const char* __name) const 522 { 523 assert(this->_M_kind != _Parameter::__unused_param); 524 const int __bufsize = 64; 525 char __buf[__bufsize]; 526 527 if (_M_kind == __iterator) 528 { 529 if (strcmp(__name, "name") == 0) 530 { 531 assert(_M_variant._M_iterator._M_name); 532 __formatter->_M_print_word(_M_variant._M_iterator._M_name); 533 } 534 else if (strcmp(__name, "address") == 0) 535 { 536 __formatter->_M_format_word(__buf, __bufsize, "%p", 537 _M_variant._M_iterator._M_address); 538 __formatter->_M_print_word(__buf); 539 } 540 else if (strcmp(__name, "type") == 0) 541 { 542 if (!_M_variant._M_iterator._M_type) 543 __formatter->_M_print_word("<unknown type>"); 544 else 545 // TBD: demangle! 546 __formatter->_M_print_word(_M_variant._M_iterator. 547 _M_type->name()); 548 } 549 else if (strcmp(__name, "constness") == 0) 550 { 551 static const char* __constness_names[__last_constness] = 552 { 553 "<unknown>", 554 "constant", 555 "mutable" 556 }; 557 __formatter->_M_print_word(__constness_names[_M_variant. 558 _M_iterator. 559 _M_constness]); 560 } 561 else if (strcmp(__name, "state") == 0) 562 { 563 static const char* __state_names[__last_state] = 564 { 565 "<unknown>", 566 "singular", 567 "dereferenceable (start-of-sequence)", 568 "dereferenceable", 569 "past-the-end", 570 "before-begin" 571 }; 572 __formatter->_M_print_word(__state_names[_M_variant. 573 _M_iterator._M_state]); 574 } 575 else if (strcmp(__name, "sequence") == 0) 576 { 577 assert(_M_variant._M_iterator._M_sequence); 578 __formatter->_M_format_word(__buf, __bufsize, "%p", 579 _M_variant._M_iterator._M_sequence); 580 __formatter->_M_print_word(__buf); 581 } 582 else if (strcmp(__name, "seq_type") == 0) 583 { 584 if (!_M_variant._M_iterator._M_seq_type) 585 __formatter->_M_print_word("<unknown seq_type>"); 586 else 587 // TBD: demangle! 588 __formatter->_M_print_word(_M_variant._M_iterator. 589 _M_seq_type->name()); 590 } 591 else 592 assert(false); 593 } 594 else if (_M_kind == __sequence) 595 { 596 if (strcmp(__name, "name") == 0) 597 { 598 assert(_M_variant._M_sequence._M_name); 599 __formatter->_M_print_word(_M_variant._M_sequence._M_name); 600 } 601 else if (strcmp(__name, "address") == 0) 602 { 603 assert(_M_variant._M_sequence._M_address); 604 __formatter->_M_format_word(__buf, __bufsize, "%p", 605 _M_variant._M_sequence._M_address); 606 __formatter->_M_print_word(__buf); 607 } 608 else if (strcmp(__name, "type") == 0) 609 { 610 if (!_M_variant._M_sequence._M_type) 611 __formatter->_M_print_word("<unknown type>"); 612 else 613 // TBD: demangle! 614 __formatter->_M_print_word(_M_variant._M_sequence. 615 _M_type->name()); 616 } 617 else 618 assert(false); 619 } 620 else if (_M_kind == __integer) 621 { 622 if (strcmp(__name, "name") == 0) 623 { 624 assert(_M_variant._M_integer._M_name); 625 __formatter->_M_print_word(_M_variant._M_integer._M_name); 626 } 627 else 628 assert(false); 629 } 630 else if (_M_kind == __string) 631 { 632 if (strcmp(__name, "name") == 0) 633 { 634 assert(_M_variant._M_string._M_name); 635 __formatter->_M_print_word(_M_variant._M_string._M_name); 636 } 637 else 638 assert(false); 639 } 640 else 641 { 642 assert(false); 643 } 644 } 645 646 void 647 _Error_formatter::_Parameter:: 648 _M_print_description(const _Error_formatter* __formatter) const 649 { 650 const int __bufsize = 128; 651 char __buf[__bufsize]; 652 653 if (_M_kind == __iterator) 654 { 655 __formatter->_M_print_word("iterator "); 656 if (_M_variant._M_iterator._M_name) 657 { 658 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 659 _M_variant._M_iterator._M_name); 660 __formatter->_M_print_word(__buf); 661 } 662 663 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 664 _M_variant._M_iterator._M_address); 665 __formatter->_M_print_word(__buf); 666 if (_M_variant._M_iterator._M_type) 667 { 668 __formatter->_M_print_word("type = "); 669 _M_print_field(__formatter, "type"); 670 671 if (_M_variant._M_iterator._M_constness != __unknown_constness) 672 { 673 __formatter->_M_print_word(" ("); 674 _M_print_field(__formatter, "constness"); 675 __formatter->_M_print_word(" iterator)"); 676 } 677 __formatter->_M_print_word(";\n"); 678 } 679 680 if (_M_variant._M_iterator._M_state != __unknown_state) 681 { 682 __formatter->_M_print_word(" state = "); 683 _M_print_field(__formatter, "state"); 684 __formatter->_M_print_word(";\n"); 685 } 686 687 if (_M_variant._M_iterator._M_sequence) 688 { 689 __formatter->_M_print_word(" references sequence "); 690 if (_M_variant._M_iterator._M_seq_type) 691 { 692 __formatter->_M_print_word("with type `"); 693 _M_print_field(__formatter, "seq_type"); 694 __formatter->_M_print_word("' "); 695 } 696 697 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n", 698 _M_variant._M_sequence._M_address); 699 __formatter->_M_print_word(__buf); 700 } 701 __formatter->_M_print_word("}\n"); 702 } 703 else if (_M_kind == __sequence) 704 { 705 __formatter->_M_print_word("sequence "); 706 if (_M_variant._M_sequence._M_name) 707 { 708 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 709 _M_variant._M_sequence._M_name); 710 __formatter->_M_print_word(__buf); 711 } 712 713 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 714 _M_variant._M_sequence._M_address); 715 __formatter->_M_print_word(__buf); 716 717 if (_M_variant._M_sequence._M_type) 718 { 719 __formatter->_M_print_word(" type = "); 720 _M_print_field(__formatter, "type"); 721 __formatter->_M_print_word(";\n"); 722 } 723 __formatter->_M_print_word("}\n"); 724 } 725 } 726 727 const _Error_formatter& 728 _Error_formatter::_M_message(_Debug_msg_id __id) const throw () 729 { return this->_M_message(_S_debug_messages[__id]); } 730 731 void 732 _Error_formatter::_M_error() const 733 { 734 const int __bufsize = 128; 735 char __buf[__bufsize]; 736 737 // Emit file & line number information 738 _M_column = 1; 739 _M_wordwrap = false; 740 if (_M_file) 741 { 742 _M_format_word(__buf, __bufsize, "%s:", _M_file); 743 _M_print_word(__buf); 744 _M_column += strlen(__buf); 745 } 746 747 if (_M_line > 0) 748 { 749 _M_format_word(__buf, __bufsize, "%u:", _M_line); 750 _M_print_word(__buf); 751 _M_column += strlen(__buf); 752 } 753 754 if (_M_max_length) 755 _M_wordwrap = true; 756 _M_print_word("error: "); 757 758 // Print the error message 759 assert(_M_text); 760 _M_print_string(_M_text); 761 _M_print_word(".\n"); 762 763 // Emit descriptions of the objects involved in the operation 764 _M_wordwrap = false; 765 bool __has_noninteger_parameters = false; 766 for (unsigned int __i = 0; __i < _M_num_parameters; ++__i) 767 { 768 if (_M_parameters[__i]._M_kind == _Parameter::__iterator 769 || _M_parameters[__i]._M_kind == _Parameter::__sequence) 770 { 771 if (!__has_noninteger_parameters) 772 { 773 _M_first_line = true; 774 _M_print_word("\nObjects involved in the operation:\n"); 775 __has_noninteger_parameters = true; 776 } 777 _M_parameters[__i]._M_print_description(this); 778 } 779 } 780 781 abort(); 782 } 783 784 template<typename _Tp> 785 void 786 _Error_formatter::_M_format_word(char* __buf, 787 int __n __attribute__ ((__unused__)), 788 const char* __fmt, _Tp __s) const throw () 789 { 790 #ifdef _GLIBCXX_USE_C99 791 std::snprintf(__buf, __n, __fmt, __s); 792 #else 793 std::sprintf(__buf, __fmt, __s); 794 #endif 795 } 796 797 798 void 799 _Error_formatter::_M_print_word(const char* __word) const 800 { 801 if (!_M_wordwrap) 802 { 803 fprintf(stderr, "%s", __word); 804 return; 805 } 806 807 size_t __length = strlen(__word); 808 if (__length == 0) 809 return; 810 811 if ((_M_column + __length < _M_max_length) 812 || (__length >= _M_max_length && _M_column == 1)) 813 { 814 // If this isn't the first line, indent 815 if (_M_column == 1 && !_M_first_line) 816 { 817 char __spacing[_M_indent + 1]; 818 for (int i = 0; i < _M_indent; ++i) 819 __spacing[i] = ' '; 820 __spacing[_M_indent] = '\0'; 821 fprintf(stderr, "%s", __spacing); 822 _M_column += _M_indent; 823 } 824 825 fprintf(stderr, "%s", __word); 826 _M_column += __length; 827 828 if (__word[__length - 1] == '\n') 829 { 830 _M_first_line = false; 831 _M_column = 1; 832 } 833 } 834 else 835 { 836 _M_column = 1; 837 _M_print_word("\n"); 838 _M_print_word(__word); 839 } 840 } 841 842 void 843 _Error_formatter:: 844 _M_print_string(const char* __string) const 845 { 846 const char* __start = __string; 847 const char* __finish = __start; 848 const int __bufsize = 128; 849 char __buf[__bufsize]; 850 851 while (*__start) 852 { 853 if (*__start != '%') 854 { 855 // [__start, __finish) denotes the next word 856 __finish = __start; 857 while (isalnum(*__finish)) 858 ++__finish; 859 if (__start == __finish) 860 ++__finish; 861 if (isspace(*__finish)) 862 ++__finish; 863 864 const ptrdiff_t __len = __finish - __start; 865 assert(__len < __bufsize); 866 memcpy(__buf, __start, __len); 867 __buf[__len] = '\0'; 868 _M_print_word(__buf); 869 __start = __finish; 870 871 // Skip extra whitespace 872 while (*__start == ' ') 873 ++__start; 874 875 continue; 876 } 877 878 ++__start; 879 assert(*__start); 880 if (*__start == '%') 881 { 882 _M_print_word("%"); 883 ++__start; 884 continue; 885 } 886 887 // Get the parameter number 888 assert(*__start >= '1' && *__start <= '9'); 889 size_t __param = *__start - '0'; 890 --__param; 891 assert(__param < _M_num_parameters); 892 893 // '.' separates the parameter number from the field 894 // name, if there is one. 895 ++__start; 896 if (*__start != '.') 897 { 898 assert(*__start == ';'); 899 ++__start; 900 __buf[0] = '\0'; 901 if (_M_parameters[__param]._M_kind == _Parameter::__integer) 902 { 903 _M_format_word(__buf, __bufsize, "%ld", 904 _M_parameters[__param]._M_variant._M_integer._M_value); 905 _M_print_word(__buf); 906 } 907 else if (_M_parameters[__param]._M_kind == _Parameter::__string) 908 _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value); 909 continue; 910 } 911 912 // Extract the field name we want 913 enum { __max_field_len = 16 }; 914 char __field[__max_field_len]; 915 int __field_idx = 0; 916 ++__start; 917 while (*__start != ';') 918 { 919 assert(*__start); 920 assert(__field_idx < __max_field_len-1); 921 __field[__field_idx++] = *__start++; 922 } 923 ++__start; 924 __field[__field_idx] = 0; 925 926 _M_parameters[__param]._M_print_field(this, __field); 927 } 928 } 929 930 void 931 _Error_formatter::_M_get_max_length() const throw () 932 { 933 const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH"); 934 if (__nptr) 935 { 936 char* __endptr; 937 const unsigned long __ret = std::strtoul(__nptr, &__endptr, 0); 938 if (*__nptr != '\0' && *__endptr == '\0') 939 _M_max_length = __ret; 940 } 941 } 942 943 // Instantiations. 944 template 945 void 946 _Error_formatter::_M_format_word(char*, int, const char*, 947 const void*) const; 948 949 template 950 void 951 _Error_formatter::_M_format_word(char*, int, const char*, long) const; 952 953 template 954 void 955 _Error_formatter::_M_format_word(char*, int, const char*, 956 std::size_t) const; 957 958 template 959 void 960 _Error_formatter::_M_format_word(char*, int, const char*, 961 const char*) const; 962 } // namespace __gnu_debug 963