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