1ffeaf689SAlexander Kabaev // Debugging mode support code -*- C++ -*- 2ffeaf689SAlexander Kabaev 3*f8a1b7d9SAlexander Kabaev // Copyright (C) 2003, 2004, 2005, 2006 4ffeaf689SAlexander Kabaev // Free Software Foundation, Inc. 5ffeaf689SAlexander Kabaev // 6ffeaf689SAlexander Kabaev // This file is part of the GNU ISO C++ Library. This library is free 7ffeaf689SAlexander Kabaev // software; you can redistribute it and/or modify it under the 8ffeaf689SAlexander Kabaev // terms of the GNU General Public License as published by the 9ffeaf689SAlexander Kabaev // Free Software Foundation; either version 2, or (at your option) 10ffeaf689SAlexander Kabaev // any later version. 11ffeaf689SAlexander Kabaev 12ffeaf689SAlexander Kabaev // This library is distributed in the hope that it will be useful, 13ffeaf689SAlexander Kabaev // but WITHOUT ANY WARRANTY; without even the implied warranty of 14ffeaf689SAlexander Kabaev // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15ffeaf689SAlexander Kabaev // GNU General Public License for more details. 16ffeaf689SAlexander Kabaev 17ffeaf689SAlexander Kabaev // You should have received a copy of the GNU General Public License along 18ffeaf689SAlexander Kabaev // with this library; see the file COPYING. If not, write to the Free 19*f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 20ffeaf689SAlexander Kabaev // USA. 21ffeaf689SAlexander Kabaev 22ffeaf689SAlexander Kabaev // As a special exception, you may use this file as part of a free software 23ffeaf689SAlexander Kabaev // library without restriction. Specifically, if other files instantiate 24ffeaf689SAlexander Kabaev // templates or use macros or inline functions from this file, or you compile 25ffeaf689SAlexander Kabaev // this file and link it with other files to produce an executable, this 26ffeaf689SAlexander Kabaev // file does not by itself cause the resulting executable to be covered by 27ffeaf689SAlexander Kabaev // the GNU General Public License. This exception does not however 28ffeaf689SAlexander Kabaev // invalidate any other reasons why the executable file might be covered by 29ffeaf689SAlexander Kabaev // the GNU General Public License. 30ffeaf689SAlexander Kabaev 31ffeaf689SAlexander Kabaev #include <debug/debug.h> 32ffeaf689SAlexander Kabaev #include <debug/safe_sequence.h> 33ffeaf689SAlexander Kabaev #include <debug/safe_iterator.h> 34ffeaf689SAlexander Kabaev #include <algorithm> 35ffeaf689SAlexander Kabaev #include <cassert> 36ffeaf689SAlexander Kabaev #include <cstring> 37ffeaf689SAlexander Kabaev #include <cctype> 38ffeaf689SAlexander Kabaev 39ffeaf689SAlexander Kabaev using namespace std; 40ffeaf689SAlexander Kabaev 41*f8a1b7d9SAlexander Kabaev namespace 42f260e61bSAlexander Kabaev { 43*f8a1b7d9SAlexander Kabaev __gnu_cxx::__mutex safe_base_mutex; 44*f8a1b7d9SAlexander Kabaev } // anonymous namespace 45f260e61bSAlexander Kabaev 46ffeaf689SAlexander Kabaev namespace __gnu_debug 47ffeaf689SAlexander Kabaev { 48ffeaf689SAlexander Kabaev const char* _S_debug_messages[] = 49ffeaf689SAlexander Kabaev { 50ffeaf689SAlexander Kabaev "function requires a valid iterator range [%1.name;, %2.name;)", 51ffeaf689SAlexander Kabaev "attempt to insert into container with a singular iterator", 52ffeaf689SAlexander Kabaev "attempt to insert into container with an iterator" 53ffeaf689SAlexander Kabaev " from a different container", 54ffeaf689SAlexander Kabaev "attempt to erase from container with a %2.state; iterator", 55ffeaf689SAlexander Kabaev "attempt to erase from container with an iterator" 56ffeaf689SAlexander Kabaev " from a different container", 57ffeaf689SAlexander Kabaev "attempt to subscript container with out-of-bounds index %2;," 58ffeaf689SAlexander Kabaev " but container only holds %3; elements", 59ffeaf689SAlexander Kabaev "attempt to access an element in an empty container", 60ffeaf689SAlexander Kabaev "elements in iterator range [%1.name;, %2.name;)" 61ffeaf689SAlexander Kabaev " are not partitioned by the value %3;", 62ffeaf689SAlexander Kabaev "elements in iterator range [%1.name;, %2.name;)" 63ffeaf689SAlexander Kabaev " are not partitioned by the predicate %3; and value %4;", 64ffeaf689SAlexander Kabaev "elements in iterator range [%1.name;, %2.name;) are not sorted", 65ffeaf689SAlexander Kabaev "elements in iterator range [%1.name;, %2.name;)" 66ffeaf689SAlexander Kabaev " are not sorted according to the predicate %3;", 67ffeaf689SAlexander Kabaev "elements in iterator range [%1.name;, %2.name;) do not form a heap", 68ffeaf689SAlexander Kabaev "elements in iterator range [%1.name;, %2.name;)" 69ffeaf689SAlexander Kabaev " do not form a heap with respect to the predicate %3;", 70ffeaf689SAlexander Kabaev "attempt to write through a singular bitset reference", 71ffeaf689SAlexander Kabaev "attempt to read from a singular bitset reference", 72ffeaf689SAlexander Kabaev "attempt to flip a singular bitset reference", 73ffeaf689SAlexander Kabaev "attempt to splice a list into itself", 74ffeaf689SAlexander Kabaev "attempt to splice lists with inequal allocators", 75ffeaf689SAlexander Kabaev "attempt to splice elements referenced by a %1.state; iterator", 76ffeaf689SAlexander Kabaev "attempt to splice an iterator from a different container", 77ffeaf689SAlexander Kabaev "splice destination %1.name;" 78ffeaf689SAlexander Kabaev " occurs within source range [%2.name;, %3.name;)", 79ffeaf689SAlexander Kabaev "attempt to initialize an iterator that will immediately become singular", 80ffeaf689SAlexander Kabaev "attempt to copy-construct an iterator from a singular iterator", 81ffeaf689SAlexander Kabaev "attempt to construct a constant iterator" 82ffeaf689SAlexander Kabaev " from a singular mutable iterator", 83ffeaf689SAlexander Kabaev "attempt to copy from a singular iterator", 84ffeaf689SAlexander Kabaev "attempt to dereference a %1.state; iterator", 85ffeaf689SAlexander Kabaev "attempt to increment a %1.state; iterator", 86ffeaf689SAlexander Kabaev "attempt to decrement a %1.state; iterator", 87ffeaf689SAlexander Kabaev "attempt to subscript a %1.state; iterator %2; step from" 88ffeaf689SAlexander Kabaev " its current position, which falls outside its dereferenceable range", 89ffeaf689SAlexander Kabaev "attempt to advance a %1.state; iterator %2; steps," 90ffeaf689SAlexander Kabaev " which falls outside its valid range", 91ffeaf689SAlexander Kabaev "attempt to retreat a %1.state; iterator %2; steps," 92ffeaf689SAlexander Kabaev " which falls outside its valid range", 93ffeaf689SAlexander Kabaev "attempt to compare a %1.state; iterator to a %2.state; iterator", 94ffeaf689SAlexander Kabaev "attempt to compare iterators from different sequences", 95ffeaf689SAlexander Kabaev "attempt to order a %1.state; iterator to a %2.state; iterator", 96ffeaf689SAlexander Kabaev "attempt to order iterators from different sequences", 97ffeaf689SAlexander Kabaev "attempt to compute the difference between a %1.state;" 98ffeaf689SAlexander Kabaev " iterator to a %2.state; iterator", 99ffeaf689SAlexander Kabaev "attempt to compute the different between two iterators" 100ffeaf689SAlexander Kabaev " from different sequences", 101ffeaf689SAlexander Kabaev "attempt to dereference an end-of-stream istream_iterator", 102ffeaf689SAlexander Kabaev "attempt to increment an end-of-stream istream_iterator", 103ffeaf689SAlexander Kabaev "attempt to output via an ostream_iterator with no associated stream", 104ffeaf689SAlexander Kabaev "attempt to dereference an end-of-stream istreambuf_iterator" 105ffeaf689SAlexander Kabaev " (this is a GNU extension)", 106ffeaf689SAlexander Kabaev "attempt to increment an end-of-stream istreambuf_iterator" 107ffeaf689SAlexander Kabaev }; 108ffeaf689SAlexander Kabaev 109ffeaf689SAlexander Kabaev void 110ffeaf689SAlexander Kabaev _Safe_sequence_base:: _M_detach_all()111ffeaf689SAlexander Kabaev _M_detach_all() 112ffeaf689SAlexander Kabaev { 113*f8a1b7d9SAlexander Kabaev __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 114ffeaf689SAlexander Kabaev for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 115ffeaf689SAlexander Kabaev { 116ffeaf689SAlexander Kabaev _Safe_iterator_base* __old = __iter; 117ffeaf689SAlexander Kabaev __iter = __iter->_M_next; 118*f8a1b7d9SAlexander Kabaev __old->_M_detach_single(); 119ffeaf689SAlexander Kabaev } 120ffeaf689SAlexander Kabaev 121ffeaf689SAlexander Kabaev for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 122ffeaf689SAlexander Kabaev { 123ffeaf689SAlexander Kabaev _Safe_iterator_base* __old = __iter2; 124ffeaf689SAlexander Kabaev __iter2 = __iter2->_M_next; 125*f8a1b7d9SAlexander Kabaev __old->_M_detach_single(); 126ffeaf689SAlexander Kabaev } 127ffeaf689SAlexander Kabaev } 128ffeaf689SAlexander Kabaev 129ffeaf689SAlexander Kabaev void 130ffeaf689SAlexander Kabaev _Safe_sequence_base:: _M_detach_singular()131ffeaf689SAlexander Kabaev _M_detach_singular() 132ffeaf689SAlexander Kabaev { 133*f8a1b7d9SAlexander Kabaev __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 134ffeaf689SAlexander Kabaev for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 135ffeaf689SAlexander Kabaev { 136ffeaf689SAlexander Kabaev _Safe_iterator_base* __old = __iter; 137ffeaf689SAlexander Kabaev __iter = __iter->_M_next; 138ffeaf689SAlexander Kabaev if (__old->_M_singular()) 139*f8a1b7d9SAlexander Kabaev __old->_M_detach_single(); 140ffeaf689SAlexander Kabaev } 141ffeaf689SAlexander Kabaev 142ffeaf689SAlexander Kabaev for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 143ffeaf689SAlexander Kabaev { 144ffeaf689SAlexander Kabaev _Safe_iterator_base* __old = __iter2; 145ffeaf689SAlexander Kabaev __iter2 = __iter2->_M_next; 146ffeaf689SAlexander Kabaev if (__old->_M_singular()) 147*f8a1b7d9SAlexander Kabaev __old->_M_detach_single(); 148ffeaf689SAlexander Kabaev } 149ffeaf689SAlexander Kabaev } 150ffeaf689SAlexander Kabaev 151ffeaf689SAlexander Kabaev void 152ffeaf689SAlexander Kabaev _Safe_sequence_base:: _M_revalidate_singular()153ffeaf689SAlexander Kabaev _M_revalidate_singular() 154ffeaf689SAlexander Kabaev { 155*f8a1b7d9SAlexander Kabaev __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 156*f8a1b7d9SAlexander Kabaev for (_Safe_iterator_base* __iter = _M_iterators; __iter; 157*f8a1b7d9SAlexander Kabaev __iter = __iter->_M_next) 158ffeaf689SAlexander Kabaev __iter->_M_version = _M_version; 159ffeaf689SAlexander Kabaev 160*f8a1b7d9SAlexander Kabaev for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; 161*f8a1b7d9SAlexander Kabaev __iter2 = __iter2->_M_next) 162*f8a1b7d9SAlexander Kabaev __iter2->_M_version = _M_version; 163ffeaf689SAlexander Kabaev } 164ffeaf689SAlexander Kabaev 165ffeaf689SAlexander Kabaev void 166ffeaf689SAlexander Kabaev _Safe_sequence_base:: _M_swap(_Safe_sequence_base & __x)167ffeaf689SAlexander Kabaev _M_swap(_Safe_sequence_base& __x) 168ffeaf689SAlexander Kabaev { 169*f8a1b7d9SAlexander Kabaev __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 170ffeaf689SAlexander Kabaev swap(_M_iterators, __x._M_iterators); 171ffeaf689SAlexander Kabaev swap(_M_const_iterators, __x._M_const_iterators); 172ffeaf689SAlexander Kabaev swap(_M_version, __x._M_version); 173ffeaf689SAlexander Kabaev _Safe_iterator_base* __iter; 174ffeaf689SAlexander Kabaev for (__iter = _M_iterators; __iter; __iter = __iter->_M_next) 175ffeaf689SAlexander Kabaev __iter->_M_sequence = this; 176ffeaf689SAlexander Kabaev for (__iter = __x._M_iterators; __iter; __iter = __iter->_M_next) 177ffeaf689SAlexander Kabaev __iter->_M_sequence = &__x; 178ffeaf689SAlexander Kabaev for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next) 179ffeaf689SAlexander Kabaev __iter->_M_sequence = this; 180ffeaf689SAlexander Kabaev for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next) 181ffeaf689SAlexander Kabaev __iter->_M_sequence = &__x; 182ffeaf689SAlexander Kabaev } 183ffeaf689SAlexander Kabaev 184*f8a1b7d9SAlexander Kabaev __gnu_cxx::__mutex& 185*f8a1b7d9SAlexander Kabaev _Safe_sequence_base:: _M_get_mutex()186*f8a1b7d9SAlexander Kabaev _M_get_mutex() 187*f8a1b7d9SAlexander Kabaev { return safe_base_mutex; } 188*f8a1b7d9SAlexander Kabaev 189ffeaf689SAlexander Kabaev void 190ffeaf689SAlexander Kabaev _Safe_iterator_base:: _M_attach(_Safe_sequence_base * __seq,bool __constant)191ffeaf689SAlexander Kabaev _M_attach(_Safe_sequence_base* __seq, bool __constant) 192ffeaf689SAlexander Kabaev { 193*f8a1b7d9SAlexander Kabaev __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 194*f8a1b7d9SAlexander Kabaev _M_attach_single(__seq, __constant); 195*f8a1b7d9SAlexander Kabaev } 196*f8a1b7d9SAlexander Kabaev 197*f8a1b7d9SAlexander Kabaev void 198*f8a1b7d9SAlexander Kabaev _Safe_iterator_base:: _M_attach_single(_Safe_sequence_base * __seq,bool __constant)199*f8a1b7d9SAlexander Kabaev _M_attach_single(_Safe_sequence_base* __seq, bool __constant) 200*f8a1b7d9SAlexander Kabaev { 201*f8a1b7d9SAlexander Kabaev _M_detach_single(); 202ffeaf689SAlexander Kabaev 203ffeaf689SAlexander Kabaev // Attach to the new sequence (if there is one) 204ffeaf689SAlexander Kabaev if (__seq) 205ffeaf689SAlexander Kabaev { 206ffeaf689SAlexander Kabaev _M_sequence = __seq; 207ffeaf689SAlexander Kabaev _M_version = _M_sequence->_M_version; 208ffeaf689SAlexander Kabaev _M_prior = 0; 209ffeaf689SAlexander Kabaev if (__constant) 210ffeaf689SAlexander Kabaev { 211ffeaf689SAlexander Kabaev _M_next = _M_sequence->_M_const_iterators; 212ffeaf689SAlexander Kabaev if (_M_next) 213ffeaf689SAlexander Kabaev _M_next->_M_prior = this; 214ffeaf689SAlexander Kabaev _M_sequence->_M_const_iterators = this; 215ffeaf689SAlexander Kabaev } 216ffeaf689SAlexander Kabaev else 217ffeaf689SAlexander Kabaev { 218ffeaf689SAlexander Kabaev _M_next = _M_sequence->_M_iterators; 219ffeaf689SAlexander Kabaev if (_M_next) 220ffeaf689SAlexander Kabaev _M_next->_M_prior = this; 221ffeaf689SAlexander Kabaev _M_sequence->_M_iterators = this; 222ffeaf689SAlexander Kabaev } 223ffeaf689SAlexander Kabaev } 224ffeaf689SAlexander Kabaev } 225ffeaf689SAlexander Kabaev 226ffeaf689SAlexander Kabaev void 227ffeaf689SAlexander Kabaev _Safe_iterator_base:: _M_detach()228ffeaf689SAlexander Kabaev _M_detach() 229ffeaf689SAlexander Kabaev { 230*f8a1b7d9SAlexander Kabaev __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 231*f8a1b7d9SAlexander Kabaev _M_detach_single(); 232*f8a1b7d9SAlexander Kabaev } 233*f8a1b7d9SAlexander Kabaev 234*f8a1b7d9SAlexander Kabaev void 235*f8a1b7d9SAlexander Kabaev _Safe_iterator_base:: _M_detach_single()236*f8a1b7d9SAlexander Kabaev _M_detach_single() 237*f8a1b7d9SAlexander Kabaev { 238ffeaf689SAlexander Kabaev if (_M_sequence) 239ffeaf689SAlexander Kabaev { 240ffeaf689SAlexander Kabaev // Remove us from this sequence's list 241ffeaf689SAlexander Kabaev if (_M_prior) 242ffeaf689SAlexander Kabaev _M_prior->_M_next = _M_next; 243ffeaf689SAlexander Kabaev if (_M_next) 244ffeaf689SAlexander Kabaev _M_next->_M_prior = _M_prior; 245ffeaf689SAlexander Kabaev 246ffeaf689SAlexander Kabaev if (_M_sequence->_M_const_iterators == this) 247ffeaf689SAlexander Kabaev _M_sequence->_M_const_iterators = _M_next; 248ffeaf689SAlexander Kabaev if (_M_sequence->_M_iterators == this) 249ffeaf689SAlexander Kabaev _M_sequence->_M_iterators = _M_next; 250ffeaf689SAlexander Kabaev } 251ffeaf689SAlexander Kabaev 252ffeaf689SAlexander Kabaev _M_sequence = 0; 253ffeaf689SAlexander Kabaev _M_version = 0; 254ffeaf689SAlexander Kabaev _M_prior = 0; 255ffeaf689SAlexander Kabaev _M_next = 0; 256ffeaf689SAlexander Kabaev } 257ffeaf689SAlexander Kabaev 258ffeaf689SAlexander Kabaev bool 259ffeaf689SAlexander Kabaev _Safe_iterator_base:: _M_singular() const260ffeaf689SAlexander Kabaev _M_singular() const 261ffeaf689SAlexander Kabaev { return !_M_sequence || _M_version != _M_sequence->_M_version; } 262ffeaf689SAlexander Kabaev 263ffeaf689SAlexander Kabaev bool 264ffeaf689SAlexander Kabaev _Safe_iterator_base:: _M_can_compare(const _Safe_iterator_base & __x) const265ffeaf689SAlexander Kabaev _M_can_compare(const _Safe_iterator_base& __x) const 266ffeaf689SAlexander Kabaev { 267*f8a1b7d9SAlexander Kabaev return (!_M_singular() 268*f8a1b7d9SAlexander Kabaev && !__x._M_singular() && _M_sequence == __x._M_sequence); 269ffeaf689SAlexander Kabaev } 270ffeaf689SAlexander Kabaev 271*f8a1b7d9SAlexander Kabaev __gnu_cxx::__mutex& 272*f8a1b7d9SAlexander Kabaev _Safe_iterator_base:: _M_get_mutex()273*f8a1b7d9SAlexander Kabaev _M_get_mutex() 274*f8a1b7d9SAlexander Kabaev { return safe_base_mutex; } 275*f8a1b7d9SAlexander Kabaev 276ffeaf689SAlexander Kabaev void 277ffeaf689SAlexander Kabaev _Error_formatter::_Parameter:: _M_print_field(const _Error_formatter * __formatter,const char * __name) const278ffeaf689SAlexander Kabaev _M_print_field(const _Error_formatter* __formatter, const char* __name) const 279ffeaf689SAlexander Kabaev { 280ffeaf689SAlexander Kabaev assert(this->_M_kind != _Parameter::__unused_param); 281ffeaf689SAlexander Kabaev const int __bufsize = 64; 282ffeaf689SAlexander Kabaev char __buf[__bufsize]; 283ffeaf689SAlexander Kabaev 284ffeaf689SAlexander Kabaev if (_M_kind == __iterator) 285ffeaf689SAlexander Kabaev { 286ffeaf689SAlexander Kabaev if (strcmp(__name, "name") == 0) 287ffeaf689SAlexander Kabaev { 288ffeaf689SAlexander Kabaev assert(_M_variant._M_iterator._M_name); 289ffeaf689SAlexander Kabaev __formatter->_M_print_word(_M_variant._M_iterator._M_name); 290ffeaf689SAlexander Kabaev } 291ffeaf689SAlexander Kabaev else if (strcmp(__name, "address") == 0) 292ffeaf689SAlexander Kabaev { 293ffeaf689SAlexander Kabaev __formatter->_M_format_word(__buf, __bufsize, "%p", 294ffeaf689SAlexander Kabaev _M_variant._M_iterator._M_address); 295ffeaf689SAlexander Kabaev __formatter->_M_print_word(__buf); 296ffeaf689SAlexander Kabaev } 297ffeaf689SAlexander Kabaev else if (strcmp(__name, "type") == 0) 298ffeaf689SAlexander Kabaev { 299ffeaf689SAlexander Kabaev assert(_M_variant._M_iterator._M_type); 300ffeaf689SAlexander Kabaev // TBD: demangle! 301ffeaf689SAlexander Kabaev __formatter->_M_print_word(_M_variant._M_iterator._M_type->name()); 302ffeaf689SAlexander Kabaev } 303ffeaf689SAlexander Kabaev else if (strcmp(__name, "constness") == 0) 304ffeaf689SAlexander Kabaev { 305ffeaf689SAlexander Kabaev static const char* __constness_names[__last_constness] = 306ffeaf689SAlexander Kabaev { 307ffeaf689SAlexander Kabaev "<unknown>", 308ffeaf689SAlexander Kabaev "constant", 309ffeaf689SAlexander Kabaev "mutable" 310ffeaf689SAlexander Kabaev }; 311ffeaf689SAlexander Kabaev __formatter->_M_print_word(__constness_names[_M_variant._M_iterator._M_constness]); 312ffeaf689SAlexander Kabaev } 313ffeaf689SAlexander Kabaev else if (strcmp(__name, "state") == 0) 314ffeaf689SAlexander Kabaev { 315ffeaf689SAlexander Kabaev static const char* __state_names[__last_state] = 316ffeaf689SAlexander Kabaev { 317ffeaf689SAlexander Kabaev "<unknown>", 318ffeaf689SAlexander Kabaev "singular", 319ffeaf689SAlexander Kabaev "dereferenceable (start-of-sequence)", 320ffeaf689SAlexander Kabaev "dereferenceable", 321ffeaf689SAlexander Kabaev "past-the-end" 322ffeaf689SAlexander Kabaev }; 323ffeaf689SAlexander Kabaev __formatter->_M_print_word(__state_names[_M_variant._M_iterator._M_state]); 324ffeaf689SAlexander Kabaev } 325ffeaf689SAlexander Kabaev else if (strcmp(__name, "sequence") == 0) 326ffeaf689SAlexander Kabaev { 327ffeaf689SAlexander Kabaev assert(_M_variant._M_iterator._M_sequence); 328ffeaf689SAlexander Kabaev __formatter->_M_format_word(__buf, __bufsize, "%p", 329ffeaf689SAlexander Kabaev _M_variant._M_iterator._M_sequence); 330ffeaf689SAlexander Kabaev __formatter->_M_print_word(__buf); 331ffeaf689SAlexander Kabaev } 332ffeaf689SAlexander Kabaev else if (strcmp(__name, "seq_type") == 0) 333ffeaf689SAlexander Kabaev { 334ffeaf689SAlexander Kabaev // TBD: demangle! 335ffeaf689SAlexander Kabaev assert(_M_variant._M_iterator._M_seq_type); 336ffeaf689SAlexander Kabaev __formatter->_M_print_word(_M_variant._M_iterator._M_seq_type->name()); 337ffeaf689SAlexander Kabaev } 338ffeaf689SAlexander Kabaev else 339ffeaf689SAlexander Kabaev assert(false); 340ffeaf689SAlexander Kabaev } 341ffeaf689SAlexander Kabaev else if (_M_kind == __sequence) 342ffeaf689SAlexander Kabaev { 343ffeaf689SAlexander Kabaev if (strcmp(__name, "name") == 0) 344ffeaf689SAlexander Kabaev { 345ffeaf689SAlexander Kabaev assert(_M_variant._M_sequence._M_name); 346ffeaf689SAlexander Kabaev __formatter->_M_print_word(_M_variant._M_sequence._M_name); 347ffeaf689SAlexander Kabaev } 348ffeaf689SAlexander Kabaev else if (strcmp(__name, "address") == 0) 349ffeaf689SAlexander Kabaev { 350ffeaf689SAlexander Kabaev assert(_M_variant._M_sequence._M_address); 351ffeaf689SAlexander Kabaev __formatter->_M_format_word(__buf, __bufsize, "%p", 352ffeaf689SAlexander Kabaev _M_variant._M_sequence._M_address); 353ffeaf689SAlexander Kabaev __formatter->_M_print_word(__buf); 354ffeaf689SAlexander Kabaev } 355ffeaf689SAlexander Kabaev else if (strcmp(__name, "type") == 0) 356ffeaf689SAlexander Kabaev { 357ffeaf689SAlexander Kabaev // TBD: demangle! 358ffeaf689SAlexander Kabaev assert(_M_variant._M_sequence._M_type); 359ffeaf689SAlexander Kabaev __formatter->_M_print_word(_M_variant._M_sequence._M_type->name()); 360ffeaf689SAlexander Kabaev } 361ffeaf689SAlexander Kabaev else 362ffeaf689SAlexander Kabaev assert(false); 363ffeaf689SAlexander Kabaev } 364ffeaf689SAlexander Kabaev else if (_M_kind == __integer) 365ffeaf689SAlexander Kabaev { 366ffeaf689SAlexander Kabaev if (strcmp(__name, "name") == 0) 367ffeaf689SAlexander Kabaev { 368ffeaf689SAlexander Kabaev assert(_M_variant._M_integer._M_name); 369ffeaf689SAlexander Kabaev __formatter->_M_print_word(_M_variant._M_integer._M_name); 370ffeaf689SAlexander Kabaev } 371ffeaf689SAlexander Kabaev else 372ffeaf689SAlexander Kabaev assert(false); 373ffeaf689SAlexander Kabaev } 374ffeaf689SAlexander Kabaev else if (_M_kind == __string) 375ffeaf689SAlexander Kabaev { 376ffeaf689SAlexander Kabaev if (strcmp(__name, "name") == 0) 377ffeaf689SAlexander Kabaev { 378ffeaf689SAlexander Kabaev assert(_M_variant._M_string._M_name); 379ffeaf689SAlexander Kabaev __formatter->_M_print_word(_M_variant._M_string._M_name); 380ffeaf689SAlexander Kabaev } 381ffeaf689SAlexander Kabaev else 382ffeaf689SAlexander Kabaev assert(false); 383ffeaf689SAlexander Kabaev } 384ffeaf689SAlexander Kabaev else 385ffeaf689SAlexander Kabaev { 386ffeaf689SAlexander Kabaev assert(false); 387ffeaf689SAlexander Kabaev } 388ffeaf689SAlexander Kabaev } 389ffeaf689SAlexander Kabaev 390ffeaf689SAlexander Kabaev void 391ffeaf689SAlexander Kabaev _Error_formatter::_Parameter:: _M_print_description(const _Error_formatter * __formatter) const392ffeaf689SAlexander Kabaev _M_print_description(const _Error_formatter* __formatter) const 393ffeaf689SAlexander Kabaev { 394ffeaf689SAlexander Kabaev const int __bufsize = 128; 395ffeaf689SAlexander Kabaev char __buf[__bufsize]; 396ffeaf689SAlexander Kabaev 397ffeaf689SAlexander Kabaev if (_M_kind == __iterator) 398ffeaf689SAlexander Kabaev { 399ffeaf689SAlexander Kabaev __formatter->_M_print_word("iterator "); 400ffeaf689SAlexander Kabaev if (_M_variant._M_iterator._M_name) 401ffeaf689SAlexander Kabaev { 402ffeaf689SAlexander Kabaev __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 403ffeaf689SAlexander Kabaev _M_variant._M_iterator._M_name); 404ffeaf689SAlexander Kabaev __formatter->_M_print_word(__buf); 405ffeaf689SAlexander Kabaev } 406ffeaf689SAlexander Kabaev 407ffeaf689SAlexander Kabaev __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 408ffeaf689SAlexander Kabaev _M_variant._M_iterator._M_address); 409ffeaf689SAlexander Kabaev __formatter->_M_print_word(__buf); 410ffeaf689SAlexander Kabaev if (_M_variant._M_iterator._M_type) 411ffeaf689SAlexander Kabaev { 412ffeaf689SAlexander Kabaev __formatter->_M_print_word("type = "); 413ffeaf689SAlexander Kabaev _M_print_field(__formatter, "type"); 414ffeaf689SAlexander Kabaev 415ffeaf689SAlexander Kabaev if (_M_variant._M_iterator._M_constness != __unknown_constness) 416ffeaf689SAlexander Kabaev { 417ffeaf689SAlexander Kabaev __formatter->_M_print_word(" ("); 418ffeaf689SAlexander Kabaev _M_print_field(__formatter, "constness"); 419ffeaf689SAlexander Kabaev __formatter->_M_print_word(" iterator)"); 420ffeaf689SAlexander Kabaev } 421ffeaf689SAlexander Kabaev __formatter->_M_print_word(";\n"); 422ffeaf689SAlexander Kabaev } 423ffeaf689SAlexander Kabaev 424ffeaf689SAlexander Kabaev if (_M_variant._M_iterator._M_state != __unknown_state) 425ffeaf689SAlexander Kabaev { 426ffeaf689SAlexander Kabaev __formatter->_M_print_word(" state = "); 427ffeaf689SAlexander Kabaev _M_print_field(__formatter, "state"); 428ffeaf689SAlexander Kabaev __formatter->_M_print_word(";\n"); 429ffeaf689SAlexander Kabaev } 430ffeaf689SAlexander Kabaev 431ffeaf689SAlexander Kabaev if (_M_variant._M_iterator._M_sequence) 432ffeaf689SAlexander Kabaev { 433ffeaf689SAlexander Kabaev __formatter->_M_print_word(" references sequence "); 434ffeaf689SAlexander Kabaev if (_M_variant._M_iterator._M_seq_type) 435ffeaf689SAlexander Kabaev { 436ffeaf689SAlexander Kabaev __formatter->_M_print_word("with type `"); 437ffeaf689SAlexander Kabaev _M_print_field(__formatter, "seq_type"); 438ffeaf689SAlexander Kabaev __formatter->_M_print_word("' "); 439ffeaf689SAlexander Kabaev } 440ffeaf689SAlexander Kabaev 441ffeaf689SAlexander Kabaev __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n", 442ffeaf689SAlexander Kabaev _M_variant._M_sequence._M_address); 443ffeaf689SAlexander Kabaev __formatter->_M_print_word(__buf); 444ffeaf689SAlexander Kabaev } 445ffeaf689SAlexander Kabaev __formatter->_M_print_word("}\n"); 446ffeaf689SAlexander Kabaev } 447ffeaf689SAlexander Kabaev else if (_M_kind == __sequence) 448ffeaf689SAlexander Kabaev { 449ffeaf689SAlexander Kabaev __formatter->_M_print_word("sequence "); 450ffeaf689SAlexander Kabaev if (_M_variant._M_sequence._M_name) 451ffeaf689SAlexander Kabaev { 452ffeaf689SAlexander Kabaev __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 453ffeaf689SAlexander Kabaev _M_variant._M_sequence._M_name); 454ffeaf689SAlexander Kabaev __formatter->_M_print_word(__buf); 455ffeaf689SAlexander Kabaev } 456ffeaf689SAlexander Kabaev 457ffeaf689SAlexander Kabaev __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 458ffeaf689SAlexander Kabaev _M_variant._M_sequence._M_address); 459ffeaf689SAlexander Kabaev __formatter->_M_print_word(__buf); 460ffeaf689SAlexander Kabaev 461ffeaf689SAlexander Kabaev if (_M_variant._M_sequence._M_type) 462ffeaf689SAlexander Kabaev { 463ffeaf689SAlexander Kabaev __formatter->_M_print_word(" type = "); 464ffeaf689SAlexander Kabaev _M_print_field(__formatter, "type"); 465ffeaf689SAlexander Kabaev __formatter->_M_print_word(";\n"); 466ffeaf689SAlexander Kabaev } 467ffeaf689SAlexander Kabaev __formatter->_M_print_word("}\n"); 468ffeaf689SAlexander Kabaev } 469ffeaf689SAlexander Kabaev } 470ffeaf689SAlexander Kabaev 471ffeaf689SAlexander Kabaev const _Error_formatter& _M_message(_Debug_msg_id __id) const472ffeaf689SAlexander Kabaev _Error_formatter::_M_message(_Debug_msg_id __id) const 473ffeaf689SAlexander Kabaev { return this->_M_message(_S_debug_messages[__id]); } 474ffeaf689SAlexander Kabaev 475ffeaf689SAlexander Kabaev void _M_error() const476ffeaf689SAlexander Kabaev _Error_formatter::_M_error() const 477ffeaf689SAlexander Kabaev { 478ffeaf689SAlexander Kabaev const int __bufsize = 128; 479ffeaf689SAlexander Kabaev char __buf[__bufsize]; 480ffeaf689SAlexander Kabaev 481ffeaf689SAlexander Kabaev // Emit file & line number information 482ffeaf689SAlexander Kabaev _M_column = 1; 483ffeaf689SAlexander Kabaev _M_wordwrap = false; 484ffeaf689SAlexander Kabaev if (_M_file) 485ffeaf689SAlexander Kabaev { 486ffeaf689SAlexander Kabaev _M_format_word(__buf, __bufsize, "%s:", _M_file); 487ffeaf689SAlexander Kabaev _M_print_word(__buf); 488ffeaf689SAlexander Kabaev _M_column += strlen(__buf); 489ffeaf689SAlexander Kabaev } 490ffeaf689SAlexander Kabaev 491ffeaf689SAlexander Kabaev if (_M_line > 0) 492ffeaf689SAlexander Kabaev { 493ffeaf689SAlexander Kabaev _M_format_word(__buf, __bufsize, "%u:", _M_line); 494ffeaf689SAlexander Kabaev _M_print_word(__buf); 495ffeaf689SAlexander Kabaev _M_column += strlen(__buf); 496ffeaf689SAlexander Kabaev } 497ffeaf689SAlexander Kabaev 498ffeaf689SAlexander Kabaev _M_wordwrap = true; 499ffeaf689SAlexander Kabaev _M_print_word("error: "); 500ffeaf689SAlexander Kabaev 501ffeaf689SAlexander Kabaev // Print the error message 502ffeaf689SAlexander Kabaev assert(_M_text); 503ffeaf689SAlexander Kabaev _M_print_string(_M_text); 504ffeaf689SAlexander Kabaev _M_print_word(".\n"); 505ffeaf689SAlexander Kabaev 506ffeaf689SAlexander Kabaev // Emit descriptions of the objects involved in the operation 507ffeaf689SAlexander Kabaev _M_wordwrap = false; 508ffeaf689SAlexander Kabaev bool __has_noninteger_parameters = false; 509ffeaf689SAlexander Kabaev for (unsigned int __i = 0; __i < _M_num_parameters; ++__i) 510ffeaf689SAlexander Kabaev { 511ffeaf689SAlexander Kabaev if (_M_parameters[__i]._M_kind == _Parameter::__iterator 512ffeaf689SAlexander Kabaev || _M_parameters[__i]._M_kind == _Parameter::__sequence) 513ffeaf689SAlexander Kabaev { 514ffeaf689SAlexander Kabaev if (!__has_noninteger_parameters) 515ffeaf689SAlexander Kabaev { 516ffeaf689SAlexander Kabaev _M_first_line = true; 517ffeaf689SAlexander Kabaev _M_print_word("\nObjects involved in the operation:\n"); 518ffeaf689SAlexander Kabaev __has_noninteger_parameters = true; 519ffeaf689SAlexander Kabaev } 520ffeaf689SAlexander Kabaev _M_parameters[__i]._M_print_description(this); 521ffeaf689SAlexander Kabaev } 522ffeaf689SAlexander Kabaev } 523ffeaf689SAlexander Kabaev 524ffeaf689SAlexander Kabaev abort(); 525ffeaf689SAlexander Kabaev } 526ffeaf689SAlexander Kabaev 527ffeaf689SAlexander Kabaev template<typename _Tp> 528ffeaf689SAlexander Kabaev void _M_format_word(char * __buf,int __n,const char * __fmt,_Tp __s) const529ffeaf689SAlexander Kabaev _Error_formatter::_M_format_word(char* __buf, 530ffeaf689SAlexander Kabaev int __n __attribute__ ((__unused__)), 531ffeaf689SAlexander Kabaev const char* __fmt, _Tp __s) const 532ffeaf689SAlexander Kabaev { 533ffeaf689SAlexander Kabaev #ifdef _GLIBCXX_USE_C99 534ffeaf689SAlexander Kabaev std::snprintf(__buf, __n, __fmt, __s); 535ffeaf689SAlexander Kabaev #else 536ffeaf689SAlexander Kabaev std::sprintf(__buf, __fmt, __s); 537ffeaf689SAlexander Kabaev #endif 538ffeaf689SAlexander Kabaev } 539ffeaf689SAlexander Kabaev 540ffeaf689SAlexander Kabaev 541ffeaf689SAlexander Kabaev void _M_print_word(const char * __word) const542ffeaf689SAlexander Kabaev _Error_formatter::_M_print_word(const char* __word) const 543ffeaf689SAlexander Kabaev { 544ffeaf689SAlexander Kabaev if (!_M_wordwrap) 545ffeaf689SAlexander Kabaev { 546ffeaf689SAlexander Kabaev fprintf(stderr, "%s", __word); 547ffeaf689SAlexander Kabaev return; 548ffeaf689SAlexander Kabaev } 549ffeaf689SAlexander Kabaev 550ffeaf689SAlexander Kabaev size_t __length = strlen(__word); 551ffeaf689SAlexander Kabaev if (__length == 0) 552ffeaf689SAlexander Kabaev return; 553ffeaf689SAlexander Kabaev 554ffeaf689SAlexander Kabaev if ((_M_column + __length < _M_max_length) 555ffeaf689SAlexander Kabaev || (__length >= _M_max_length && _M_column == 1)) 556ffeaf689SAlexander Kabaev { 557ffeaf689SAlexander Kabaev // If this isn't the first line, indent 558ffeaf689SAlexander Kabaev if (_M_column == 1 && !_M_first_line) 559ffeaf689SAlexander Kabaev { 560ffeaf689SAlexander Kabaev char __spacing[_M_indent + 1]; 561ffeaf689SAlexander Kabaev for (int i = 0; i < _M_indent; ++i) 562ffeaf689SAlexander Kabaev __spacing[i] = ' '; 563ffeaf689SAlexander Kabaev __spacing[_M_indent] = '\0'; 564ffeaf689SAlexander Kabaev fprintf(stderr, "%s", __spacing); 565ffeaf689SAlexander Kabaev _M_column += _M_indent; 566ffeaf689SAlexander Kabaev } 567ffeaf689SAlexander Kabaev 568ffeaf689SAlexander Kabaev fprintf(stderr, "%s", __word); 569ffeaf689SAlexander Kabaev _M_column += __length; 570ffeaf689SAlexander Kabaev 571ffeaf689SAlexander Kabaev if (__word[__length - 1] == '\n') 572ffeaf689SAlexander Kabaev { 573ffeaf689SAlexander Kabaev _M_first_line = false; 574ffeaf689SAlexander Kabaev _M_column = 1; 575ffeaf689SAlexander Kabaev } 576ffeaf689SAlexander Kabaev } 577ffeaf689SAlexander Kabaev else 578ffeaf689SAlexander Kabaev { 579ffeaf689SAlexander Kabaev _M_column = 1; 580ffeaf689SAlexander Kabaev _M_print_word("\n"); 581ffeaf689SAlexander Kabaev _M_print_word(__word); 582ffeaf689SAlexander Kabaev } 583ffeaf689SAlexander Kabaev } 584ffeaf689SAlexander Kabaev 585ffeaf689SAlexander Kabaev void 586ffeaf689SAlexander Kabaev _Error_formatter:: _M_print_string(const char * __string) const587ffeaf689SAlexander Kabaev _M_print_string(const char* __string) const 588ffeaf689SAlexander Kabaev { 589ffeaf689SAlexander Kabaev const char* __start = __string; 590*f8a1b7d9SAlexander Kabaev const char* __finish = __start; 591ffeaf689SAlexander Kabaev const int __bufsize = 128; 592ffeaf689SAlexander Kabaev char __buf[__bufsize]; 593ffeaf689SAlexander Kabaev 594ffeaf689SAlexander Kabaev while (*__start) 595ffeaf689SAlexander Kabaev { 596ffeaf689SAlexander Kabaev if (*__start != '%') 597ffeaf689SAlexander Kabaev { 598*f8a1b7d9SAlexander Kabaev // [__start, __finish) denotes the next word 599*f8a1b7d9SAlexander Kabaev __finish = __start; 600*f8a1b7d9SAlexander Kabaev while (isalnum(*__finish)) 601*f8a1b7d9SAlexander Kabaev ++__finish; 602*f8a1b7d9SAlexander Kabaev if (__start == __finish) 603*f8a1b7d9SAlexander Kabaev ++__finish; 604*f8a1b7d9SAlexander Kabaev if (isspace(*__finish)) 605*f8a1b7d9SAlexander Kabaev ++__finish; 606ffeaf689SAlexander Kabaev 607*f8a1b7d9SAlexander Kabaev const ptrdiff_t __len = __finish - __start; 608f260e61bSAlexander Kabaev assert(__len < __bufsize); 609f260e61bSAlexander Kabaev memcpy(__buf, __start, __len); 610f260e61bSAlexander Kabaev __buf[__len] = '\0'; 611ffeaf689SAlexander Kabaev _M_print_word(__buf); 612*f8a1b7d9SAlexander Kabaev __start = __finish; 613ffeaf689SAlexander Kabaev 614ffeaf689SAlexander Kabaev // Skip extra whitespace 615ffeaf689SAlexander Kabaev while (*__start == ' ') 616ffeaf689SAlexander Kabaev ++__start; 617ffeaf689SAlexander Kabaev 618ffeaf689SAlexander Kabaev continue; 619ffeaf689SAlexander Kabaev } 620ffeaf689SAlexander Kabaev 621ffeaf689SAlexander Kabaev ++__start; 622ffeaf689SAlexander Kabaev assert(*__start); 623ffeaf689SAlexander Kabaev if (*__start == '%') 624ffeaf689SAlexander Kabaev { 625ffeaf689SAlexander Kabaev _M_print_word("%"); 626ffeaf689SAlexander Kabaev ++__start; 627ffeaf689SAlexander Kabaev continue; 628ffeaf689SAlexander Kabaev } 629ffeaf689SAlexander Kabaev 630ffeaf689SAlexander Kabaev // Get the parameter number 631ffeaf689SAlexander Kabaev assert(*__start >= '1' && *__start <= '9'); 632ffeaf689SAlexander Kabaev size_t __param = *__start - '0'; 633ffeaf689SAlexander Kabaev --__param; 634ffeaf689SAlexander Kabaev assert(__param < _M_num_parameters); 635ffeaf689SAlexander Kabaev 636ffeaf689SAlexander Kabaev // '.' separates the parameter number from the field 637ffeaf689SAlexander Kabaev // name, if there is one. 638ffeaf689SAlexander Kabaev ++__start; 639ffeaf689SAlexander Kabaev if (*__start != '.') 640ffeaf689SAlexander Kabaev { 641ffeaf689SAlexander Kabaev assert(*__start == ';'); 642ffeaf689SAlexander Kabaev ++__start; 643ffeaf689SAlexander Kabaev __buf[0] = '\0'; 644ffeaf689SAlexander Kabaev if (_M_parameters[__param]._M_kind == _Parameter::__integer) 645ffeaf689SAlexander Kabaev { 646ffeaf689SAlexander Kabaev _M_format_word(__buf, __bufsize, "%ld", 647ffeaf689SAlexander Kabaev _M_parameters[__param]._M_variant._M_integer._M_value); 648ffeaf689SAlexander Kabaev _M_print_word(__buf); 649ffeaf689SAlexander Kabaev } 650ffeaf689SAlexander Kabaev else if (_M_parameters[__param]._M_kind == _Parameter::__string) 651ffeaf689SAlexander Kabaev _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value); 652ffeaf689SAlexander Kabaev continue; 653ffeaf689SAlexander Kabaev } 654ffeaf689SAlexander Kabaev 655ffeaf689SAlexander Kabaev // Extract the field name we want 656ffeaf689SAlexander Kabaev enum { __max_field_len = 16 }; 657ffeaf689SAlexander Kabaev char __field[__max_field_len]; 658ffeaf689SAlexander Kabaev int __field_idx = 0; 659ffeaf689SAlexander Kabaev ++__start; 660ffeaf689SAlexander Kabaev while (*__start != ';') 661ffeaf689SAlexander Kabaev { 662ffeaf689SAlexander Kabaev assert(*__start); 663ffeaf689SAlexander Kabaev assert(__field_idx < __max_field_len-1); 664ffeaf689SAlexander Kabaev __field[__field_idx++] = *__start++; 665ffeaf689SAlexander Kabaev } 666ffeaf689SAlexander Kabaev ++__start; 667ffeaf689SAlexander Kabaev __field[__field_idx] = 0; 668ffeaf689SAlexander Kabaev 669ffeaf689SAlexander Kabaev _M_parameters[__param]._M_print_field(this, __field); 670ffeaf689SAlexander Kabaev } 671ffeaf689SAlexander Kabaev } 672ffeaf689SAlexander Kabaev 673ffeaf689SAlexander Kabaev // Instantiations. 674ffeaf689SAlexander Kabaev template 675ffeaf689SAlexander Kabaev void 676*f8a1b7d9SAlexander Kabaev _Error_formatter::_M_format_word(char*, int, const char*, 677*f8a1b7d9SAlexander Kabaev const void*) const; 678ffeaf689SAlexander Kabaev 679ffeaf689SAlexander Kabaev template 680ffeaf689SAlexander Kabaev void 681*f8a1b7d9SAlexander Kabaev _Error_formatter::_M_format_word(char*, int, const char*, long) const; 682ffeaf689SAlexander Kabaev 683ffeaf689SAlexander Kabaev template 684ffeaf689SAlexander Kabaev void 685*f8a1b7d9SAlexander Kabaev _Error_formatter::_M_format_word(char*, int, const char*, 686*f8a1b7d9SAlexander Kabaev std::size_t) const; 687ffeaf689SAlexander Kabaev 688ffeaf689SAlexander Kabaev template 689ffeaf689SAlexander Kabaev void 690*f8a1b7d9SAlexander Kabaev _Error_formatter::_M_format_word(char*, int, const char*, 691*f8a1b7d9SAlexander Kabaev const char*) const; 692ffeaf689SAlexander Kabaev } // namespace __gnu_debug 693