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