2012-01-13 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libstdc++-v3 / src / debug.cc
blobaf45ae4f543a6fb6bc7db9183a3230f954e59b59
1 // Debugging mode support code -*- C++ -*-
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.
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.
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.
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/>.
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>
39 using namespace std;
41 namespace
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)
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];
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)
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;
69 void
70 swap_seq(__gnu_debug::_Safe_sequence_base& __lhs,
71 __gnu_debug::_Safe_sequence_base& __rhs)
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);
80 void
81 swap_ucont(__gnu_debug::_Safe_unordered_container_base& __lhs,
82 __gnu_debug::_Safe_unordered_container_base& __rhs)
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);
91 void
92 detach_all(__gnu_debug::_Safe_iterator_base* __iter)
94 for (; __iter;)
96 __gnu_debug::_Safe_iterator_base* __old = __iter;
97 __iter = __iter->_M_next;
98 __old->_M_reset();
101 } // anonymous namespace
103 namespace __gnu_debug
105 const char* _S_debug_messages[] =
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;)"
183 void
184 _Safe_sequence_base::
185 _M_detach_all()
187 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
188 detach_all(_M_iterators);
189 _M_iterators = 0;
191 detach_all(_M_const_iterators);
192 _M_const_iterators = 0;
195 void
196 _Safe_sequence_base::
197 _M_detach_singular()
199 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
200 for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
202 _Safe_iterator_base* __old = __iter;
203 __iter = __iter->_M_next;
204 if (__old->_M_singular())
205 __old->_M_detach_single();
208 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
210 _Safe_iterator_base* __old = __iter2;
211 __iter2 = __iter2->_M_next;
212 if (__old->_M_singular())
213 __old->_M_detach_single();
217 void
218 _Safe_sequence_base::
219 _M_revalidate_singular()
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;
226 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
227 __iter2 = __iter2->_M_next)
228 __iter2->_M_version = _M_version;
231 void
232 _Safe_sequence_base::
233 _M_swap(_Safe_sequence_base& __x)
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)
241 __scoped_lock __lock(*__this_mutex);
242 swap_seq(*this, __x);
244 else
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);
254 __gnu_cxx::__mutex&
255 _Safe_sequence_base::
256 _M_get_mutex() throw ()
257 { return get_safe_base_mutex(this); }
259 void
260 _Safe_sequence_base::
261 _M_attach(_Safe_iterator_base* __it, bool __constant)
263 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
264 _M_attach_single(__it, __constant);
267 void
268 _Safe_sequence_base::
269 _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ()
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;
279 void
280 _Safe_sequence_base::
281 _M_detach(_Safe_iterator_base* __it)
283 // Remove __it from this sequence's list
284 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
285 _M_detach_single(__it);
288 void
289 _Safe_sequence_base::
290 _M_detach_single(_Safe_iterator_base* __it) throw ()
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;
300 void
301 _Safe_iterator_base::
302 _M_attach(_Safe_sequence_base* __seq, bool __constant)
304 _M_detach();
306 // Attach to the new sequence (if there is one)
307 if (__seq)
309 _M_sequence = __seq;
310 _M_version = _M_sequence->_M_version;
311 _M_sequence->_M_attach(this, __constant);
315 void
316 _Safe_iterator_base::
317 _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ()
319 _M_detach_single();
321 // Attach to the new sequence (if there is one)
322 if (__seq)
324 _M_sequence = __seq;
325 _M_version = _M_sequence->_M_version;
326 _M_sequence->_M_attach_single(this, __constant);
330 void
331 _Safe_iterator_base::
332 _M_detach()
334 if (_M_sequence)
335 _M_sequence->_M_detach(this);
337 _M_reset();
340 void
341 _Safe_iterator_base::
342 _M_detach_single() throw ()
344 if (_M_sequence)
345 _M_sequence->_M_detach_single(this);
347 _M_reset();
350 void
351 _Safe_iterator_base::
352 _M_reset() throw ()
354 _M_sequence = 0;
355 _M_version = 0;
356 _M_prior = 0;
357 _M_next = 0;
360 bool
361 _Safe_iterator_base::
362 _M_singular() const throw ()
363 { return !_M_sequence || _M_version != _M_sequence->_M_version; }
365 bool
366 _Safe_iterator_base::
367 _M_can_compare(const _Safe_iterator_base& __x) const throw ()
369 return (!_M_singular()
370 && !__x._M_singular() && _M_sequence == __x._M_sequence);
373 __gnu_cxx::__mutex&
374 _Safe_iterator_base::
375 _M_get_mutex() throw ()
376 { return get_safe_base_mutex(_M_sequence); }
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); }
383 void
384 _Safe_local_iterator_base::
385 _M_attach(_Safe_sequence_base* __cont, bool __constant)
387 _M_detach();
389 // Attach to the new container (if there is one)
390 if (__cont)
392 _M_sequence = __cont;
393 _M_version = _M_sequence->_M_version;
394 _M_get_container()->_M_attach_local(this, __constant);
398 void
399 _Safe_local_iterator_base::
400 _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw ()
402 _M_detach_single();
404 // Attach to the new container (if there is one)
405 if (__cont)
407 _M_sequence = __cont;
408 _M_version = _M_sequence->_M_version;
409 _M_get_container()->_M_attach_local_single(this, __constant);
413 void
414 _Safe_local_iterator_base::
415 _M_detach()
417 if (_M_sequence)
418 _M_get_container()->_M_detach_local(this);
420 _M_reset();
423 void
424 _Safe_local_iterator_base::
425 _M_detach_single() throw ()
427 if (_M_sequence)
428 _M_get_container()->_M_detach_local_single(this);
430 _M_reset();
433 void
434 _Safe_unordered_container_base::
435 _M_detach_all()
437 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
438 detach_all(_M_iterators);
439 _M_iterators = 0;
441 detach_all(_M_const_iterators);
442 _M_const_iterators = 0;
444 detach_all(_M_local_iterators);
445 _M_local_iterators = 0;
447 detach_all(_M_const_local_iterators);
448 _M_const_local_iterators = 0;
451 void
452 _Safe_unordered_container_base::
453 _M_swap(_Safe_unordered_container_base& __x)
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)
461 __scoped_lock __lock(*__this_mutex);
462 swap_ucont(*this, __x);
464 else
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);
474 void
475 _Safe_unordered_container_base::
476 _M_attach_local(_Safe_iterator_base* __it, bool __constant)
478 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
479 _M_attach_local_single(__it, __constant);
482 void
483 _Safe_unordered_container_base::
484 _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ()
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;
494 void
495 _Safe_unordered_container_base::
496 _M_detach_local(_Safe_iterator_base* __it)
498 // Remove __it from this container's list
499 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
500 _M_detach_local_single(__it);
503 void
504 _Safe_unordered_container_base::
505 _M_detach_local_single(_Safe_iterator_base* __it) throw ()
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;
515 void
516 _Error_formatter::_Parameter::
517 _M_print_field(const _Error_formatter* __formatter, const char* __name) const
519 assert(this->_M_kind != _Parameter::__unused_param);
520 const int __bufsize = 64;
521 char __buf[__bufsize];
523 if (_M_kind == __iterator)
525 if (strcmp(__name, "name") == 0)
527 assert(_M_variant._M_iterator._M_name);
528 __formatter->_M_print_word(_M_variant._M_iterator._M_name);
530 else if (strcmp(__name, "address") == 0)
532 __formatter->_M_format_word(__buf, __bufsize, "%p",
533 _M_variant._M_iterator._M_address);
534 __formatter->_M_print_word(__buf);
536 else if (strcmp(__name, "type") == 0)
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());
545 else if (strcmp(__name, "constness") == 0)
547 static const char* __constness_names[__last_constness] =
549 "<unknown>",
550 "constant",
551 "mutable"
553 __formatter->_M_print_word(__constness_names[_M_variant.
554 _M_iterator.
555 _M_constness]);
557 else if (strcmp(__name, "state") == 0)
559 static const char* __state_names[__last_state] =
561 "<unknown>",
562 "singular",
563 "dereferenceable (start-of-sequence)",
564 "dereferenceable",
565 "past-the-end",
566 "before-begin"
568 __formatter->_M_print_word(__state_names[_M_variant.
569 _M_iterator._M_state]);
571 else if (strcmp(__name, "sequence") == 0)
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);
578 else if (strcmp(__name, "seq_type") == 0)
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());
587 else
588 assert(false);
590 else if (_M_kind == __sequence)
592 if (strcmp(__name, "name") == 0)
594 assert(_M_variant._M_sequence._M_name);
595 __formatter->_M_print_word(_M_variant._M_sequence._M_name);
597 else if (strcmp(__name, "address") == 0)
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);
604 else if (strcmp(__name, "type") == 0)
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());
613 else
614 assert(false);
616 else if (_M_kind == __integer)
618 if (strcmp(__name, "name") == 0)
620 assert(_M_variant._M_integer._M_name);
621 __formatter->_M_print_word(_M_variant._M_integer._M_name);
623 else
624 assert(false);
626 else if (_M_kind == __string)
628 if (strcmp(__name, "name") == 0)
630 assert(_M_variant._M_string._M_name);
631 __formatter->_M_print_word(_M_variant._M_string._M_name);
633 else
634 assert(false);
636 else
638 assert(false);
642 void
643 _Error_formatter::_Parameter::
644 _M_print_description(const _Error_formatter* __formatter) const
646 const int __bufsize = 128;
647 char __buf[__bufsize];
649 if (_M_kind == __iterator)
651 __formatter->_M_print_word("iterator ");
652 if (_M_variant._M_iterator._M_name)
654 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
655 _M_variant._M_iterator._M_name);
656 __formatter->_M_print_word(__buf);
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)
664 __formatter->_M_print_word("type = ");
665 _M_print_field(__formatter, "type");
667 if (_M_variant._M_iterator._M_constness != __unknown_constness)
669 __formatter->_M_print_word(" (");
670 _M_print_field(__formatter, "constness");
671 __formatter->_M_print_word(" iterator)");
673 __formatter->_M_print_word(";\n");
676 if (_M_variant._M_iterator._M_state != __unknown_state)
678 __formatter->_M_print_word(" state = ");
679 _M_print_field(__formatter, "state");
680 __formatter->_M_print_word(";\n");
683 if (_M_variant._M_iterator._M_sequence)
685 __formatter->_M_print_word(" references sequence ");
686 if (_M_variant._M_iterator._M_seq_type)
688 __formatter->_M_print_word("with type `");
689 _M_print_field(__formatter, "seq_type");
690 __formatter->_M_print_word("' ");
693 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n",
694 _M_variant._M_sequence._M_address);
695 __formatter->_M_print_word(__buf);
697 __formatter->_M_print_word("}\n");
699 else if (_M_kind == __sequence)
701 __formatter->_M_print_word("sequence ");
702 if (_M_variant._M_sequence._M_name)
704 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
705 _M_variant._M_sequence._M_name);
706 __formatter->_M_print_word(__buf);
709 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
710 _M_variant._M_sequence._M_address);
711 __formatter->_M_print_word(__buf);
713 if (_M_variant._M_sequence._M_type)
715 __formatter->_M_print_word(" type = ");
716 _M_print_field(__formatter, "type");
717 __formatter->_M_print_word(";\n");
719 __formatter->_M_print_word("}\n");
723 const _Error_formatter&
724 _Error_formatter::_M_message(_Debug_msg_id __id) const throw ()
725 { return this->_M_message(_S_debug_messages[__id]); }
727 void
728 _Error_formatter::_M_error() const
730 const int __bufsize = 128;
731 char __buf[__bufsize];
733 // Emit file & line number information
734 _M_column = 1;
735 _M_wordwrap = false;
736 if (_M_file)
738 _M_format_word(__buf, __bufsize, "%s:", _M_file);
739 _M_print_word(__buf);
740 _M_column += strlen(__buf);
743 if (_M_line > 0)
745 _M_format_word(__buf, __bufsize, "%u:", _M_line);
746 _M_print_word(__buf);
747 _M_column += strlen(__buf);
750 if (_M_max_length)
751 _M_wordwrap = true;
752 _M_print_word("error: ");
754 // Print the error message
755 assert(_M_text);
756 _M_print_string(_M_text);
757 _M_print_word(".\n");
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)
764 if (_M_parameters[__i]._M_kind == _Parameter::__iterator
765 || _M_parameters[__i]._M_kind == _Parameter::__sequence)
767 if (!__has_noninteger_parameters)
769 _M_first_line = true;
770 _M_print_word("\nObjects involved in the operation:\n");
771 __has_noninteger_parameters = true;
773 _M_parameters[__i]._M_print_description(this);
777 abort();
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 ()
786 #ifdef _GLIBCXX_USE_C99
787 std::snprintf(__buf, __n, __fmt, __s);
788 #else
789 std::sprintf(__buf, __fmt, __s);
790 #endif
794 void
795 _Error_formatter::_M_print_word(const char* __word) const
797 if (!_M_wordwrap)
799 fprintf(stderr, "%s", __word);
800 return;
803 size_t __length = strlen(__word);
804 if (__length == 0)
805 return;
807 if ((_M_column + __length < _M_max_length)
808 || (__length >= _M_max_length && _M_column == 1))
810 // If this isn't the first line, indent
811 if (_M_column == 1 && !_M_first_line)
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;
821 fprintf(stderr, "%s", __word);
822 _M_column += __length;
824 if (__word[__length - 1] == '\n')
826 _M_first_line = false;
827 _M_column = 1;
830 else
832 _M_column = 1;
833 _M_print_word("\n");
834 _M_print_word(__word);
838 void
839 _Error_formatter::
840 _M_print_string(const char* __string) const
842 const char* __start = __string;
843 const char* __finish = __start;
844 const int __bufsize = 128;
845 char __buf[__bufsize];
847 while (*__start)
849 if (*__start != '%')
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;
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;
867 // Skip extra whitespace
868 while (*__start == ' ')
869 ++__start;
871 continue;
874 ++__start;
875 assert(*__start);
876 if (*__start == '%')
878 _M_print_word("%");
879 ++__start;
880 continue;
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);
889 // '.' separates the parameter number from the field
890 // name, if there is one.
891 ++__start;
892 if (*__start != '.')
894 assert(*__start == ';');
895 ++__start;
896 __buf[0] = '\0';
897 if (_M_parameters[__param]._M_kind == _Parameter::__integer)
899 _M_format_word(__buf, __bufsize, "%ld",
900 _M_parameters[__param]._M_variant._M_integer._M_value);
901 _M_print_word(__buf);
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;
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 != ';')
915 assert(*__start);
916 assert(__field_idx < __max_field_len-1);
917 __field[__field_idx++] = *__start++;
919 ++__start;
920 __field[__field_idx] = 0;
922 _M_parameters[__param]._M_print_field(this, __field);
926 void
927 _Error_formatter::_M_get_max_length() const throw ()
929 const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
930 if (__nptr)
932 char* __endptr;
933 const unsigned long __ret = std::strtoul(__nptr, &__endptr, 0);
934 if (*__nptr != '\0' && *__endptr == '\0')
935 _M_max_length = __ret;
939 // Instantiations.
940 template
941 void
942 _Error_formatter::_M_format_word(char*, int, const char*,
943 const void*) const;
945 template
946 void
947 _Error_formatter::_M_format_word(char*, int, const char*, long) const;
949 template
950 void
951 _Error_formatter::_M_format_word(char*, int, const char*,
952 std::size_t) const;
954 template
955 void
956 _Error_formatter::_M_format_word(char*, int, const char*,
957 const char*) const;
958 } // namespace __gnu_debug