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