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