Support slim switch for cfg graph dump
[official-gcc.git] / libstdc++-v3 / src / c++11 / debug.cc
blob3655f392f7a4963229df9577c4f6e61f47a57de1
1 // Debugging mode support code -*- C++ -*-
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.
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.
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.
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/>.
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>
38 using namespace std;
40 namespace
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)
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];
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)
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;
68 void
69 swap_seq(__gnu_debug::_Safe_sequence_base& __lhs,
70 __gnu_debug::_Safe_sequence_base& __rhs)
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);
79 void
80 swap_ucont(__gnu_debug::_Safe_unordered_container_base& __lhs,
81 __gnu_debug::_Safe_unordered_container_base& __rhs)
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);
90 void
91 detach_all(__gnu_debug::_Safe_iterator_base* __iter)
93 for (; __iter;)
95 __gnu_debug::_Safe_iterator_base* __old = __iter;
96 __iter = __iter->_M_next;
97 __old->_M_reset();
100 } // anonymous namespace
102 namespace __gnu_debug
104 const char* _S_debug_messages[] =
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"
187 void
188 _Safe_sequence_base::
189 _M_detach_all()
191 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
192 detach_all(_M_iterators);
193 _M_iterators = 0;
195 detach_all(_M_const_iterators);
196 _M_const_iterators = 0;
199 void
200 _Safe_sequence_base::
201 _M_detach_singular()
203 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
204 for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
206 _Safe_iterator_base* __old = __iter;
207 __iter = __iter->_M_next;
208 if (__old->_M_singular())
209 __old->_M_detach_single();
212 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
214 _Safe_iterator_base* __old = __iter2;
215 __iter2 = __iter2->_M_next;
216 if (__old->_M_singular())
217 __old->_M_detach_single();
221 void
222 _Safe_sequence_base::
223 _M_revalidate_singular()
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;
230 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
231 __iter2 = __iter2->_M_next)
232 __iter2->_M_version = _M_version;
235 void
236 _Safe_sequence_base::
237 _M_swap(_Safe_sequence_base& __x)
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)
245 __scoped_lock __lock(*__this_mutex);
246 swap_seq(*this, __x);
248 else
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);
258 __gnu_cxx::__mutex&
259 _Safe_sequence_base::
260 _M_get_mutex() throw ()
261 { return get_safe_base_mutex(this); }
263 void
264 _Safe_sequence_base::
265 _M_attach(_Safe_iterator_base* __it, bool __constant)
267 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
268 _M_attach_single(__it, __constant);
271 void
272 _Safe_sequence_base::
273 _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ()
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;
283 void
284 _Safe_sequence_base::
285 _M_detach(_Safe_iterator_base* __it)
287 // Remove __it from this sequence's list
288 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
289 _M_detach_single(__it);
292 void
293 _Safe_sequence_base::
294 _M_detach_single(_Safe_iterator_base* __it) throw ()
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;
304 void
305 _Safe_iterator_base::
306 _M_attach(_Safe_sequence_base* __seq, bool __constant)
308 _M_detach();
310 // Attach to the new sequence (if there is one)
311 if (__seq)
313 _M_sequence = __seq;
314 _M_version = _M_sequence->_M_version;
315 _M_sequence->_M_attach(this, __constant);
319 void
320 _Safe_iterator_base::
321 _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ()
323 _M_detach_single();
325 // Attach to the new sequence (if there is one)
326 if (__seq)
328 _M_sequence = __seq;
329 _M_version = _M_sequence->_M_version;
330 _M_sequence->_M_attach_single(this, __constant);
334 void
335 _Safe_iterator_base::
336 _M_detach()
338 if (_M_sequence)
339 _M_sequence->_M_detach(this);
341 _M_reset();
344 void
345 _Safe_iterator_base::
346 _M_detach_single() throw ()
348 if (_M_sequence)
349 _M_sequence->_M_detach_single(this);
351 _M_reset();
354 void
355 _Safe_iterator_base::
356 _M_reset() throw ()
358 _M_sequence = 0;
359 _M_version = 0;
360 _M_prior = 0;
361 _M_next = 0;
364 bool
365 _Safe_iterator_base::
366 _M_singular() const throw ()
367 { return !_M_sequence || _M_version != _M_sequence->_M_version; }
369 bool
370 _Safe_iterator_base::
371 _M_can_compare(const _Safe_iterator_base& __x) const throw ()
373 return (!_M_singular()
374 && !__x._M_singular() && _M_sequence == __x._M_sequence);
377 __gnu_cxx::__mutex&
378 _Safe_iterator_base::
379 _M_get_mutex() throw ()
380 { return get_safe_base_mutex(_M_sequence); }
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); }
387 void
388 _Safe_local_iterator_base::
389 _M_attach(_Safe_sequence_base* __cont, bool __constant)
391 _M_detach();
393 // Attach to the new container (if there is one)
394 if (__cont)
396 _M_sequence = __cont;
397 _M_version = _M_sequence->_M_version;
398 _M_get_container()->_M_attach_local(this, __constant);
402 void
403 _Safe_local_iterator_base::
404 _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw ()
406 _M_detach_single();
408 // Attach to the new container (if there is one)
409 if (__cont)
411 _M_sequence = __cont;
412 _M_version = _M_sequence->_M_version;
413 _M_get_container()->_M_attach_local_single(this, __constant);
417 void
418 _Safe_local_iterator_base::
419 _M_detach()
421 if (_M_sequence)
422 _M_get_container()->_M_detach_local(this);
424 _M_reset();
427 void
428 _Safe_local_iterator_base::
429 _M_detach_single() throw ()
431 if (_M_sequence)
432 _M_get_container()->_M_detach_local_single(this);
434 _M_reset();
437 void
438 _Safe_unordered_container_base::
439 _M_detach_all()
441 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
442 detach_all(_M_iterators);
443 _M_iterators = 0;
445 detach_all(_M_const_iterators);
446 _M_const_iterators = 0;
448 detach_all(_M_local_iterators);
449 _M_local_iterators = 0;
451 detach_all(_M_const_local_iterators);
452 _M_const_local_iterators = 0;
455 void
456 _Safe_unordered_container_base::
457 _M_swap(_Safe_unordered_container_base& __x)
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)
465 __scoped_lock __lock(*__this_mutex);
466 swap_ucont(*this, __x);
468 else
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);
478 void
479 _Safe_unordered_container_base::
480 _M_attach_local(_Safe_iterator_base* __it, bool __constant)
482 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
483 _M_attach_local_single(__it, __constant);
486 void
487 _Safe_unordered_container_base::
488 _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ()
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;
498 void
499 _Safe_unordered_container_base::
500 _M_detach_local(_Safe_iterator_base* __it)
502 // Remove __it from this container's list
503 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
504 _M_detach_local_single(__it);
507 void
508 _Safe_unordered_container_base::
509 _M_detach_local_single(_Safe_iterator_base* __it) throw ()
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;
519 void
520 _Error_formatter::_Parameter::
521 _M_print_field(const _Error_formatter* __formatter, const char* __name) const
523 assert(this->_M_kind != _Parameter::__unused_param);
524 const int __bufsize = 64;
525 char __buf[__bufsize];
527 if (_M_kind == __iterator)
529 if (strcmp(__name, "name") == 0)
531 assert(_M_variant._M_iterator._M_name);
532 __formatter->_M_print_word(_M_variant._M_iterator._M_name);
534 else if (strcmp(__name, "address") == 0)
536 __formatter->_M_format_word(__buf, __bufsize, "%p",
537 _M_variant._M_iterator._M_address);
538 __formatter->_M_print_word(__buf);
540 else if (strcmp(__name, "type") == 0)
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());
549 else if (strcmp(__name, "constness") == 0)
551 static const char* __constness_names[__last_constness] =
553 "<unknown>",
554 "constant",
555 "mutable"
557 __formatter->_M_print_word(__constness_names[_M_variant.
558 _M_iterator.
559 _M_constness]);
561 else if (strcmp(__name, "state") == 0)
563 static const char* __state_names[__last_state] =
565 "<unknown>",
566 "singular",
567 "dereferenceable (start-of-sequence)",
568 "dereferenceable",
569 "past-the-end",
570 "before-begin"
572 __formatter->_M_print_word(__state_names[_M_variant.
573 _M_iterator._M_state]);
575 else if (strcmp(__name, "sequence") == 0)
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);
582 else if (strcmp(__name, "seq_type") == 0)
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());
591 else
592 assert(false);
594 else if (_M_kind == __sequence)
596 if (strcmp(__name, "name") == 0)
598 assert(_M_variant._M_sequence._M_name);
599 __formatter->_M_print_word(_M_variant._M_sequence._M_name);
601 else if (strcmp(__name, "address") == 0)
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);
608 else if (strcmp(__name, "type") == 0)
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());
617 else
618 assert(false);
620 else if (_M_kind == __integer)
622 if (strcmp(__name, "name") == 0)
624 assert(_M_variant._M_integer._M_name);
625 __formatter->_M_print_word(_M_variant._M_integer._M_name);
627 else
628 assert(false);
630 else if (_M_kind == __string)
632 if (strcmp(__name, "name") == 0)
634 assert(_M_variant._M_string._M_name);
635 __formatter->_M_print_word(_M_variant._M_string._M_name);
637 else
638 assert(false);
640 else
642 assert(false);
646 void
647 _Error_formatter::_Parameter::
648 _M_print_description(const _Error_formatter* __formatter) const
650 const int __bufsize = 128;
651 char __buf[__bufsize];
653 if (_M_kind == __iterator)
655 __formatter->_M_print_word("iterator ");
656 if (_M_variant._M_iterator._M_name)
658 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
659 _M_variant._M_iterator._M_name);
660 __formatter->_M_print_word(__buf);
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)
668 __formatter->_M_print_word("type = ");
669 _M_print_field(__formatter, "type");
671 if (_M_variant._M_iterator._M_constness != __unknown_constness)
673 __formatter->_M_print_word(" (");
674 _M_print_field(__formatter, "constness");
675 __formatter->_M_print_word(" iterator)");
677 __formatter->_M_print_word(";\n");
680 if (_M_variant._M_iterator._M_state != __unknown_state)
682 __formatter->_M_print_word(" state = ");
683 _M_print_field(__formatter, "state");
684 __formatter->_M_print_word(";\n");
687 if (_M_variant._M_iterator._M_sequence)
689 __formatter->_M_print_word(" references sequence ");
690 if (_M_variant._M_iterator._M_seq_type)
692 __formatter->_M_print_word("with type `");
693 _M_print_field(__formatter, "seq_type");
694 __formatter->_M_print_word("' ");
697 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n",
698 _M_variant._M_sequence._M_address);
699 __formatter->_M_print_word(__buf);
701 __formatter->_M_print_word("}\n");
703 else if (_M_kind == __sequence)
705 __formatter->_M_print_word("sequence ");
706 if (_M_variant._M_sequence._M_name)
708 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
709 _M_variant._M_sequence._M_name);
710 __formatter->_M_print_word(__buf);
713 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
714 _M_variant._M_sequence._M_address);
715 __formatter->_M_print_word(__buf);
717 if (_M_variant._M_sequence._M_type)
719 __formatter->_M_print_word(" type = ");
720 _M_print_field(__formatter, "type");
721 __formatter->_M_print_word(";\n");
723 __formatter->_M_print_word("}\n");
727 const _Error_formatter&
728 _Error_formatter::_M_message(_Debug_msg_id __id) const throw ()
729 { return this->_M_message(_S_debug_messages[__id]); }
731 void
732 _Error_formatter::_M_error() const
734 const int __bufsize = 128;
735 char __buf[__bufsize];
737 // Emit file & line number information
738 _M_column = 1;
739 _M_wordwrap = false;
740 if (_M_file)
742 _M_format_word(__buf, __bufsize, "%s:", _M_file);
743 _M_print_word(__buf);
744 _M_column += strlen(__buf);
747 if (_M_line > 0)
749 _M_format_word(__buf, __bufsize, "%u:", _M_line);
750 _M_print_word(__buf);
751 _M_column += strlen(__buf);
754 if (_M_max_length)
755 _M_wordwrap = true;
756 _M_print_word("error: ");
758 // Print the error message
759 assert(_M_text);
760 _M_print_string(_M_text);
761 _M_print_word(".\n");
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)
768 if (_M_parameters[__i]._M_kind == _Parameter::__iterator
769 || _M_parameters[__i]._M_kind == _Parameter::__sequence)
771 if (!__has_noninteger_parameters)
773 _M_first_line = true;
774 _M_print_word("\nObjects involved in the operation:\n");
775 __has_noninteger_parameters = true;
777 _M_parameters[__i]._M_print_description(this);
781 abort();
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 ()
790 #ifdef _GLIBCXX_USE_C99
791 std::snprintf(__buf, __n, __fmt, __s);
792 #else
793 std::sprintf(__buf, __fmt, __s);
794 #endif
798 void
799 _Error_formatter::_M_print_word(const char* __word) const
801 if (!_M_wordwrap)
803 fprintf(stderr, "%s", __word);
804 return;
807 size_t __length = strlen(__word);
808 if (__length == 0)
809 return;
811 if ((_M_column + __length < _M_max_length)
812 || (__length >= _M_max_length && _M_column == 1))
814 // If this isn't the first line, indent
815 if (_M_column == 1 && !_M_first_line)
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;
825 fprintf(stderr, "%s", __word);
826 _M_column += __length;
828 if (__word[__length - 1] == '\n')
830 _M_first_line = false;
831 _M_column = 1;
834 else
836 _M_column = 1;
837 _M_print_word("\n");
838 _M_print_word(__word);
842 void
843 _Error_formatter::
844 _M_print_string(const char* __string) const
846 const char* __start = __string;
847 const char* __finish = __start;
848 const int __bufsize = 128;
849 char __buf[__bufsize];
851 while (*__start)
853 if (*__start != '%')
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;
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;
871 // Skip extra whitespace
872 while (*__start == ' ')
873 ++__start;
875 continue;
878 ++__start;
879 assert(*__start);
880 if (*__start == '%')
882 _M_print_word("%");
883 ++__start;
884 continue;
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);
893 // '.' separates the parameter number from the field
894 // name, if there is one.
895 ++__start;
896 if (*__start != '.')
898 assert(*__start == ';');
899 ++__start;
900 __buf[0] = '\0';
901 if (_M_parameters[__param]._M_kind == _Parameter::__integer)
903 _M_format_word(__buf, __bufsize, "%ld",
904 _M_parameters[__param]._M_variant._M_integer._M_value);
905 _M_print_word(__buf);
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;
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 != ';')
919 assert(*__start);
920 assert(__field_idx < __max_field_len-1);
921 __field[__field_idx++] = *__start++;
923 ++__start;
924 __field[__field_idx] = 0;
926 _M_parameters[__param]._M_print_field(this, __field);
930 void
931 _Error_formatter::_M_get_max_length() const throw ()
933 const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
934 if (__nptr)
936 char* __endptr;
937 const unsigned long __ret = std::strtoul(__nptr, &__endptr, 0);
938 if (*__nptr != '\0' && *__endptr == '\0')
939 _M_max_length = __ret;
943 // Instantiations.
944 template
945 void
946 _Error_formatter::_M_format_word(char*, int, const char*,
947 const void*) const;
949 template
950 void
951 _Error_formatter::_M_format_word(char*, int, const char*, long) const;
953 template
954 void
955 _Error_formatter::_M_format_word(char*, int, const char*,
956 std::size_t) const;
958 template
959 void
960 _Error_formatter::_M_format_word(char*, int, const char*,
961 const char*) const;
962 } // namespace __gnu_debug