1 // Debugging mode support code -*- C++ -*-
3 // Copyright (C) 2003-2015 Free Software Foundation, Inc.
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)
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_base.h>
27 #include <debug/safe_unordered_base.h>
28 #include <debug/safe_iterator.h>
29 #include <debug/safe_local_iterator.h>
38 #include <cxxabi.h> // for __cxa_demangle
44 /** Returns different instances of __mutex depending on the passed address
45 * in order to limit contention without breaking current library binary
48 get_safe_base_mutex(void* __address
)
50 const size_t mask
= 0xf;
51 static __gnu_cxx::__mutex safe_base_mutex
[mask
+ 1];
52 const size_t index
= _Hash_impl::hash(__address
) & mask
;
53 return safe_base_mutex
[index
];
57 swap_its(__gnu_debug::_Safe_sequence_base
& __lhs
,
58 __gnu_debug::_Safe_iterator_base
*& __lhs_its
,
59 __gnu_debug::_Safe_sequence_base
& __rhs
,
60 __gnu_debug::_Safe_iterator_base
*& __rhs_its
)
62 swap(__lhs_its
, __rhs_its
);
63 __gnu_debug::_Safe_iterator_base
* __iter
;
64 for (__iter
= __rhs_its
; __iter
; __iter
= __iter
->_M_next
)
65 __iter
->_M_sequence
= &__rhs
;
66 for (__iter
= __lhs_its
; __iter
; __iter
= __iter
->_M_next
)
67 __iter
->_M_sequence
= &__lhs
;
71 swap_seq(__gnu_debug::_Safe_sequence_base
& __lhs
,
72 __gnu_debug::_Safe_sequence_base
& __rhs
)
74 swap(__lhs
._M_version
, __rhs
._M_version
);
75 swap_its(__lhs
, __lhs
._M_iterators
,
76 __rhs
, __rhs
._M_iterators
);
77 swap_its(__lhs
, __lhs
._M_const_iterators
,
78 __rhs
, __rhs
._M_const_iterators
);
82 swap_ucont(__gnu_debug::_Safe_unordered_container_base
& __lhs
,
83 __gnu_debug::_Safe_unordered_container_base
& __rhs
)
85 swap_seq(__lhs
, __rhs
);
86 swap_its(__lhs
, __lhs
._M_local_iterators
,
87 __rhs
, __rhs
._M_local_iterators
);
88 swap_its(__lhs
, __lhs
._M_const_local_iterators
,
89 __rhs
, __rhs
._M_const_local_iterators
);
93 detach_all(__gnu_debug::_Safe_iterator_base
* __iter
)
97 __gnu_debug::_Safe_iterator_base
* __old
= __iter
;
98 __iter
= __iter
->_M_next
;
102 } // anonymous namespace
104 namespace __gnu_debug
106 const char* _S_debug_messages
[] =
109 "function requires a valid iterator range [%1.name;, %2.name;)",
110 "attempt to insert into container with a singular iterator",
111 "attempt to insert into container with an iterator"
112 " from a different container",
113 "attempt to erase from container with a %2.state; iterator",
114 "attempt to erase from container with an iterator"
115 " from a different container",
116 "attempt to subscript container with out-of-bounds index %2;,"
117 " but container only holds %3; elements",
118 "attempt to access an element in an empty container",
119 "elements in iterator range [%1.name;, %2.name;)"
120 " are not partitioned by the value %3;",
121 "elements in iterator range [%1.name;, %2.name;)"
122 " are not partitioned by the predicate %3; and value %4;",
123 "elements in iterator range [%1.name;, %2.name;) are not sorted",
124 "elements in iterator range [%1.name;, %2.name;)"
125 " are not sorted according to the predicate %3;",
126 "elements in iterator range [%1.name;, %2.name;) do not form a heap",
127 "elements in iterator range [%1.name;, %2.name;)"
128 " do not form a heap with respect to the predicate %3;",
129 // std::bitset checks
130 "attempt to write through a singular bitset reference",
131 "attempt to read from a singular bitset reference",
132 "attempt to flip a singular bitset reference",
134 "attempt to splice a list into itself",
135 "attempt to splice lists with unequal allocators",
136 "attempt to splice elements referenced by a %1.state; iterator",
137 "attempt to splice an iterator from a different container",
138 "splice destination %1.name;"
139 " occurs within source range [%2.name;, %3.name;)",
141 "attempt to initialize an iterator that will immediately become singular",
142 "attempt to copy-construct an iterator from a singular iterator",
143 "attempt to construct a constant iterator"
144 " from a singular mutable iterator",
145 "attempt to copy from a singular iterator",
146 "attempt to dereference a %1.state; iterator",
147 "attempt to increment a %1.state; iterator",
148 "attempt to decrement a %1.state; iterator",
149 "attempt to subscript a %1.state; iterator %2; step from"
150 " its current position, which falls outside its dereferenceable range",
151 "attempt to advance a %1.state; iterator %2; steps,"
152 " which falls outside its valid range",
153 "attempt to retreat a %1.state; iterator %2; steps,"
154 " which falls outside its valid range",
155 "attempt to compare a %1.state; iterator to a %2.state; iterator",
156 "attempt to compare iterators from different sequences",
157 "attempt to order a %1.state; iterator to a %2.state; iterator",
158 "attempt to order iterators from different sequences",
159 "attempt to compute the difference between a %1.state;"
160 " iterator to a %2.state; iterator",
161 "attempt to compute the different between two iterators"
162 " from different sequences",
164 "attempt to dereference an end-of-stream istream_iterator",
165 "attempt to increment an end-of-stream istream_iterator",
167 "attempt to output via an ostream_iterator with no associated stream",
168 // istreambuf_iterator
169 "attempt to dereference an end-of-stream istreambuf_iterator"
170 " (this is a GNU extension)",
171 "attempt to increment an end-of-stream istreambuf_iterator",
173 "attempt to insert into container after an end iterator",
174 "attempt to erase from container after a %2.state; iterator not followed"
175 " by a dereferenceable one",
176 "function requires a valid iterator range (%2.name;, %3.name;)"
177 ", \"%2.name;\" shall be before and not equal to \"%3.name;\"",
178 // std::unordered_container::local_iterator
179 "attempt to compare local iterators from different unordered container"
181 "function requires a non-empty iterator range [%1.name;, %2.name;)",
182 "attempt to self move assign",
183 "attempt to access container with out-of-bounds bucket index %2;,"
184 " container only holds %3; buckets",
185 "load factor shall be positive",
186 "allocators must be equal",
187 "attempt to insert with an iterator range [%1.name;, %2.name;) from this"
189 "comparison doesn't meet irreflexive requirements, assert(!(a < a))"
193 _Safe_sequence_base::
196 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
197 detach_all(_M_iterators
);
200 detach_all(_M_const_iterators
);
201 _M_const_iterators
= 0;
205 _Safe_sequence_base::
208 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
209 for (_Safe_iterator_base
* __iter
= _M_iterators
; __iter
;)
211 _Safe_iterator_base
* __old
= __iter
;
212 __iter
= __iter
->_M_next
;
213 if (__old
->_M_singular())
214 __old
->_M_detach_single();
217 for (_Safe_iterator_base
* __iter2
= _M_const_iterators
; __iter2
;)
219 _Safe_iterator_base
* __old
= __iter2
;
220 __iter2
= __iter2
->_M_next
;
221 if (__old
->_M_singular())
222 __old
->_M_detach_single();
227 _Safe_sequence_base::
228 _M_revalidate_singular()
230 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
231 for (_Safe_iterator_base
* __iter
= _M_iterators
; __iter
;
232 __iter
= __iter
->_M_next
)
233 __iter
->_M_version
= _M_version
;
235 for (_Safe_iterator_base
* __iter2
= _M_const_iterators
; __iter2
;
236 __iter2
= __iter2
->_M_next
)
237 __iter2
->_M_version
= _M_version
;
241 _Safe_sequence_base::
242 _M_swap(_Safe_sequence_base
& __x
) noexcept
244 // We need to lock both sequences to swap
245 using namespace __gnu_cxx
;
246 __mutex
*__this_mutex
= &_M_get_mutex();
247 __mutex
*__x_mutex
= &__x
._M_get_mutex();
248 if (__this_mutex
== __x_mutex
)
250 __scoped_lock
__lock(*__this_mutex
);
251 swap_seq(*this, __x
);
255 __scoped_lock
__l1(__this_mutex
< __x_mutex
256 ? *__this_mutex
: *__x_mutex
);
257 __scoped_lock
__l2(__this_mutex
< __x_mutex
258 ? *__x_mutex
: *__this_mutex
);
259 swap_seq(*this, __x
);
264 _Safe_sequence_base::
265 _M_get_mutex() throw ()
266 { return get_safe_base_mutex(this); }
269 _Safe_sequence_base::
270 _M_attach(_Safe_iterator_base
* __it
, bool __constant
)
272 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
273 _M_attach_single(__it
, __constant
);
277 _Safe_sequence_base::
278 _M_attach_single(_Safe_iterator_base
* __it
, bool __constant
) throw ()
280 _Safe_iterator_base
*& __its
=
281 __constant
? _M_const_iterators
: _M_iterators
;
282 __it
->_M_next
= __its
;
284 __it
->_M_next
->_M_prior
= __it
;
289 _Safe_sequence_base::
290 _M_detach(_Safe_iterator_base
* __it
)
292 // Remove __it from this sequence's list
293 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
294 _M_detach_single(__it
);
298 _Safe_sequence_base::
299 _M_detach_single(_Safe_iterator_base
* __it
) throw ()
301 // Remove __it from this sequence's list
303 if (_M_const_iterators
== __it
)
304 _M_const_iterators
= __it
->_M_next
;
305 if (_M_iterators
== __it
)
306 _M_iterators
= __it
->_M_next
;
310 _Safe_iterator_base::
311 _M_attach(_Safe_sequence_base
* __seq
, bool __constant
)
315 // Attach to the new sequence (if there is one)
319 _M_version
= _M_sequence
->_M_version
;
320 _M_sequence
->_M_attach(this, __constant
);
325 _Safe_iterator_base::
326 _M_attach_single(_Safe_sequence_base
* __seq
, bool __constant
) throw ()
330 // Attach to the new sequence (if there is one)
334 _M_version
= _M_sequence
->_M_version
;
335 _M_sequence
->_M_attach_single(this, __constant
);
340 _Safe_iterator_base::
344 _M_sequence
->_M_detach(this);
350 _Safe_iterator_base::
351 _M_detach_single() throw ()
354 _M_sequence
->_M_detach_single(this);
360 _Safe_iterator_base::
370 _Safe_iterator_base::
371 _M_singular() const throw ()
372 { return !_M_sequence
|| _M_version
!= _M_sequence
->_M_version
; }
375 _Safe_iterator_base::
376 _M_can_compare(const _Safe_iterator_base
& __x
) const throw ()
378 return (!_M_singular()
379 && !__x
._M_singular() && _M_sequence
== __x
._M_sequence
);
383 _Safe_iterator_base::
384 _M_get_mutex() throw ()
385 { return get_safe_base_mutex(_M_sequence
); }
387 _Safe_unordered_container_base
*
388 _Safe_local_iterator_base::
389 _M_get_container() const noexcept
390 { return static_cast<_Safe_unordered_container_base
*>(_M_sequence
); }
393 _Safe_local_iterator_base::
394 _M_attach(_Safe_sequence_base
* __cont
, bool __constant
)
398 // Attach to the new container (if there is one)
401 _M_sequence
= __cont
;
402 _M_version
= _M_sequence
->_M_version
;
403 _M_get_container()->_M_attach_local(this, __constant
);
408 _Safe_local_iterator_base::
409 _M_attach_single(_Safe_sequence_base
* __cont
, bool __constant
) throw ()
413 // Attach to the new container (if there is one)
416 _M_sequence
= __cont
;
417 _M_version
= _M_sequence
->_M_version
;
418 _M_get_container()->_M_attach_local_single(this, __constant
);
423 _Safe_local_iterator_base::
427 _M_get_container()->_M_detach_local(this);
433 _Safe_local_iterator_base::
434 _M_detach_single() throw ()
437 _M_get_container()->_M_detach_local_single(this);
443 _Safe_unordered_container_base::
446 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
447 detach_all(_M_iterators
);
450 detach_all(_M_const_iterators
);
451 _M_const_iterators
= 0;
453 detach_all(_M_local_iterators
);
454 _M_local_iterators
= 0;
456 detach_all(_M_const_local_iterators
);
457 _M_const_local_iterators
= 0;
461 _Safe_unordered_container_base::
462 _M_swap(_Safe_unordered_container_base
& __x
) noexcept
464 // We need to lock both containers to swap
465 using namespace __gnu_cxx
;
466 __mutex
*__this_mutex
= &_M_get_mutex();
467 __mutex
*__x_mutex
= &__x
._M_get_mutex();
468 if (__this_mutex
== __x_mutex
)
470 __scoped_lock
__lock(*__this_mutex
);
471 swap_ucont(*this, __x
);
475 __scoped_lock
__l1(__this_mutex
< __x_mutex
476 ? *__this_mutex
: *__x_mutex
);
477 __scoped_lock
__l2(__this_mutex
< __x_mutex
478 ? *__x_mutex
: *__this_mutex
);
479 swap_ucont(*this, __x
);
484 _Safe_unordered_container_base::
485 _M_attach_local(_Safe_iterator_base
* __it
, bool __constant
)
487 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
488 _M_attach_local_single(__it
, __constant
);
492 _Safe_unordered_container_base::
493 _M_attach_local_single(_Safe_iterator_base
* __it
, bool __constant
) throw ()
495 _Safe_iterator_base
*& __its
=
496 __constant
? _M_const_local_iterators
: _M_local_iterators
;
497 __it
->_M_next
= __its
;
499 __it
->_M_next
->_M_prior
= __it
;
504 _Safe_unordered_container_base::
505 _M_detach_local(_Safe_iterator_base
* __it
)
507 // Remove __it from this container's list
508 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
509 _M_detach_local_single(__it
);
513 _Safe_unordered_container_base::
514 _M_detach_local_single(_Safe_iterator_base
* __it
) throw ()
516 // Remove __it from this container's list
518 if (_M_const_local_iterators
== __it
)
519 _M_const_local_iterators
= __it
->_M_next
;
520 if (_M_local_iterators
== __it
)
521 _M_local_iterators
= __it
->_M_next
;
528 print_type(const __gnu_debug::_Error_formatter
* __formatter
,
529 const type_info
* __info
,
530 const char* __unknown_name
)
533 __formatter
->_M_print_word(__unknown_name
);
537 char* __demangled_name
=
538 __cxxabiv1::__cxa_demangle(__info
->name(), NULL
, NULL
, &__status
);
539 __formatter
->_M_print_word(__status
== 0
540 ? __demangled_name
: __info
->name());
541 free(__demangled_name
);
547 const __gnu_debug::_Error_formatter
* __formatter
,
549 const __gnu_debug::_Error_formatter::_Parameter::_Type
& __variant
)
551 if (strcmp(__name
, "name") == 0)
553 assert(__variant
._M_name
);
554 __formatter
->_M_print_word(__variant
._M_name
);
556 else if (strcmp(__name
, "type") == 0)
557 print_type(__formatter
, __variant
._M_type
, "<unknown type>");
566 const __gnu_debug::_Error_formatter
* __formatter
,
568 const __gnu_debug::_Error_formatter::_Parameter::_Instance
& __variant
)
570 const __gnu_debug::_Error_formatter::_Parameter::_Type
& __type
= __variant
;
571 if (print_field(__formatter
, __name
, __type
))
573 else if (strcmp(__name
, "address") == 0)
575 const int __bufsize
= 64;
576 char __buf
[__bufsize
];
577 __formatter
->_M_format_word(__buf
, __bufsize
, "%p",
578 __variant
._M_address
);
579 __formatter
->_M_print_word(__buf
);
589 const __gnu_debug::_Error_formatter
* __formatter
,
590 const __gnu_debug::_Error_formatter::_Parameter::_Type
& __variant
)
592 if (__variant
._M_name
)
594 const int __bufsize
= 64;
595 char __buf
[__bufsize
];
596 __formatter
->_M_format_word(__buf
, __bufsize
, "\"%s\"",
598 __formatter
->_M_print_word(__buf
);
601 __formatter
->_M_print_word(" {\n");
603 if (__variant
._M_type
)
605 __formatter
->_M_print_word(" type = ");
606 print_type(__formatter
, __variant
._M_type
, "<unknown type>");
607 __formatter
->_M_print_word(";\n");
614 const __gnu_debug::_Error_formatter
* __formatter
,
615 const __gnu_debug::_Error_formatter::_Parameter::_Instance
& __variant
)
617 const int __bufsize
= 64;
618 char __buf
[__bufsize
];
620 if (__variant
._M_name
)
622 __formatter
->_M_format_word(__buf
, __bufsize
, "\"%s\" ",
624 __formatter
->_M_print_word(__buf
);
627 __formatter
->_M_format_word(__buf
, __bufsize
, "@ 0x%p {\n",
628 __variant
._M_address
);
629 __formatter
->_M_print_word(__buf
);
631 if (__variant
._M_type
)
633 __formatter
->_M_print_word(" type = ");
634 print_type(__formatter
, __variant
._M_type
, "<unknown type>");
639 namespace __gnu_debug
642 _Error_formatter::_Parameter::
643 _M_print_field(const _Error_formatter
* __formatter
, const char* __name
) const
645 assert(this->_M_kind
!= _Parameter::__unused_param
);
646 const int __bufsize
= 64;
647 char __buf
[__bufsize
];
652 if (print_field(__formatter
, __name
, _M_variant
._M_iterator
))
654 else if (strcmp(__name
, "constness") == 0)
656 static const char* __constness_names
[__last_constness
] =
662 __formatter
->_M_print_word(__constness_names
[_M_variant
.
666 else if (strcmp(__name
, "state") == 0)
668 static const char* __state_names
[__last_state
] =
672 "dereferenceable (start-of-sequence)",
677 __formatter
->_M_print_word(__state_names
[_M_variant
.
678 _M_iterator
._M_state
]);
680 else if (strcmp(__name
, "sequence") == 0)
682 assert(_M_variant
._M_iterator
._M_sequence
);
683 __formatter
->_M_format_word(__buf
, __bufsize
, "%p",
684 _M_variant
._M_iterator
._M_sequence
);
685 __formatter
->_M_print_word(__buf
);
687 else if (strcmp(__name
, "seq_type") == 0)
688 print_type(__formatter
, _M_variant
._M_iterator
._M_seq_type
,
689 "<unknown seq_type>");
694 if (!print_field(__formatter
, __name
, _M_variant
._M_sequence
))
698 if (strcmp(__name
, "name") == 0)
700 assert(_M_variant
._M_integer
._M_name
);
701 __formatter
->_M_print_word(_M_variant
._M_integer
._M_name
);
707 if (strcmp(__name
, "name") == 0)
709 assert(_M_variant
._M_string
._M_name
);
710 __formatter
->_M_print_word(_M_variant
._M_string
._M_name
);
716 if (!print_field(__formatter
, __name
, _M_variant
._M_instance
))
719 case __iterator_value_type
:
720 if (!print_field(__formatter
, __name
, _M_variant
._M_iterator_value_type
))
730 _Error_formatter::_Parameter::
731 _M_print_description(const _Error_formatter
* __formatter
) const
733 const int __bufsize
= 128;
734 char __buf
[__bufsize
];
739 __formatter
->_M_print_word("iterator ");
740 print_description(__formatter
, _M_variant
._M_iterator
);
742 if (_M_variant
._M_iterator
._M_type
)
744 if (_M_variant
._M_iterator
._M_constness
!= __unknown_constness
)
746 __formatter
->_M_print_word(" (");
747 _M_print_field(__formatter
, "constness");
748 __formatter
->_M_print_word(" iterator)");
750 __formatter
->_M_print_word(";\n");
753 if (_M_variant
._M_iterator
._M_state
!= __unknown_state
)
755 __formatter
->_M_print_word(" state = ");
756 _M_print_field(__formatter
, "state");
757 __formatter
->_M_print_word(";\n");
760 if (_M_variant
._M_iterator
._M_sequence
)
762 __formatter
->_M_print_word(" references sequence ");
763 if (_M_variant
._M_iterator
._M_seq_type
)
765 __formatter
->_M_print_word("with type `");
766 _M_print_field(__formatter
, "seq_type");
767 __formatter
->_M_print_word("' ");
770 __formatter
->_M_format_word(__buf
, __bufsize
, "@ 0x%p\n",
771 _M_variant
._M_iterator
._M_sequence
);
772 __formatter
->_M_print_word(__buf
);
775 __formatter
->_M_print_word("}\n");
778 __formatter
->_M_print_word("sequence ");
779 print_description(__formatter
, _M_variant
._M_sequence
);
781 if (_M_variant
._M_sequence
._M_type
)
782 __formatter
->_M_print_word(";\n");
784 __formatter
->_M_print_word("}\n");
787 __formatter
->_M_print_word("instance ");
788 print_description(__formatter
, _M_variant
._M_instance
);
790 if (_M_variant
._M_instance
._M_type
)
791 __formatter
->_M_print_word(";\n");
793 __formatter
->_M_print_word("}\n");
795 case __iterator_value_type
:
796 __formatter
->_M_print_word("iterator::value_type ");
797 print_description(__formatter
, _M_variant
._M_iterator_value_type
);
798 __formatter
->_M_print_word("}\n");
805 const _Error_formatter
&
806 _Error_formatter::_M_message(_Debug_msg_id __id
) const throw ()
807 { return this->_M_message(_S_debug_messages
[__id
]); }
810 _Error_formatter::_M_error() const
812 const int __bufsize
= 128;
813 char __buf
[__bufsize
];
815 // Emit file & line number information
820 _M_format_word(__buf
, __bufsize
, "%s:", _M_file
);
821 _M_print_word(__buf
);
822 _M_column
+= strlen(__buf
);
827 _M_format_word(__buf
, __bufsize
, "%u:", _M_line
);
828 _M_print_word(__buf
);
829 _M_column
+= strlen(__buf
);
834 _M_print_word("error: ");
836 // Print the error message
838 _M_print_string(_M_text
);
839 _M_print_word(".\n");
841 // Emit descriptions of the objects involved in the operation
843 bool __has_noninteger_parameters
= false;
844 for (unsigned int __i
= 0; __i
< _M_num_parameters
; ++__i
)
846 switch (_M_parameters
[__i
]._M_kind
)
848 case _Parameter::__iterator
:
849 case _Parameter::__sequence
:
850 case _Parameter::__instance
:
851 case _Parameter::__iterator_value_type
:
852 if (!__has_noninteger_parameters
)
854 _M_first_line
= true;
855 _M_print_word("\nObjects involved in the operation:\n");
856 __has_noninteger_parameters
= true;
858 _M_parameters
[__i
]._M_print_description(this);
868 template<typename _Tp
>
870 _Error_formatter::_M_format_word(char* __buf
,
871 int __n
__attribute__ ((__unused__
)),
872 const char* __fmt
, _Tp __s
) const throw ()
874 #ifdef _GLIBCXX_USE_C99
875 std::snprintf(__buf
, __n
, __fmt
, __s
);
877 std::sprintf(__buf
, __fmt
, __s
);
882 _Error_formatter::_M_print_word(const char* __word
) const
886 fprintf(stderr
, "%s", __word
);
890 size_t __length
= strlen(__word
);
894 size_t __visual_length
895 = __word
[__length
- 1] == '\n' ? __length
- 1 : __length
;
896 if (__visual_length
== 0
897 || (_M_column
+ __visual_length
< _M_max_length
)
898 || (__visual_length
>= _M_max_length
&& _M_column
== 1))
900 // If this isn't the first line, indent
901 if (_M_column
== 1 && !_M_first_line
)
903 char __spacing
[_M_indent
+ 1];
904 for (int i
= 0; i
< _M_indent
; ++i
)
906 __spacing
[_M_indent
] = '\0';
907 fprintf(stderr
, "%s", __spacing
);
908 _M_column
+= _M_indent
;
911 fprintf(stderr
, "%s", __word
);
913 if (__word
[__length
- 1] == '\n')
915 _M_first_line
= false;
919 _M_column
+= __length
;
924 _M_print_word(__word
);
930 _M_print_string(const char* __string
) const
932 const char* __start
= __string
;
933 const char* __finish
= __start
;
934 const int __bufsize
= 128;
935 char __buf
[__bufsize
];
941 // [__start, __finish) denotes the next word
943 while (isalnum(*__finish
))
945 if (__start
== __finish
)
947 if (isspace(*__finish
))
950 const ptrdiff_t __len
= __finish
- __start
;
951 assert(__len
< __bufsize
);
952 memcpy(__buf
, __start
, __len
);
954 _M_print_word(__buf
);
957 // Skip extra whitespace
958 while (*__start
== ' ')
973 // Get the parameter number
974 assert(*__start
>= '1' && *__start
<= '9');
975 size_t __param_index
= *__start
- '0' - 1;
976 assert(__param_index
< _M_num_parameters
);
977 const auto& __param
= _M_parameters
[__param_index
];
979 // '.' separates the parameter number from the field
980 // name, if there is one.
984 assert(*__start
== ';');
987 if (__param
._M_kind
== _Parameter::__integer
)
989 _M_format_word(__buf
, __bufsize
, "%ld",
990 __param
._M_variant
._M_integer
._M_value
);
991 _M_print_word(__buf
);
993 else if (__param
._M_kind
== _Parameter::__string
)
994 _M_print_string(__param
._M_variant
._M_string
._M_value
);
998 // Extract the field name we want
999 enum { __max_field_len
= 16 };
1000 char __field
[__max_field_len
];
1001 int __field_idx
= 0;
1003 while (*__start
!= ';')
1006 assert(__field_idx
< __max_field_len
-1);
1007 __field
[__field_idx
++] = *__start
++;
1010 __field
[__field_idx
] = 0;
1012 __param
._M_print_field(this, __field
);
1017 _Error_formatter::_M_get_max_length() const throw ()
1019 const char* __nptr
= std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
1023 const unsigned long __ret
= std::strtoul(__nptr
, &__endptr
, 0);
1024 if (*__nptr
!= '\0' && *__endptr
== '\0')
1025 _M_max_length
= __ret
;
1032 _Error_formatter::_M_format_word(char*, int, const char*,
1037 _Error_formatter::_M_format_word(char*, int, const char*, long) const;
1041 _Error_formatter::_M_format_word(char*, int, const char*,
1046 _Error_formatter::_M_format_word(char*, int, const char*,
1048 } // namespace __gnu_debug