xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/src/c++11/debug.cc (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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