Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libstdc++-v3 / src / c++11 / debug.cc
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