1 // Debugging mode support code -*- C++ -*-
3 // Copyright (C) 2003-2014 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>
42 /** Returns different instances of __mutex depending on the passed address
43 * in order to limit contention without breaking current library binary
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
];
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
;
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
);
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
);
91 detach_all(__gnu_debug::_Safe_iterator_base
* __iter
)
95 __gnu_debug::_Safe_iterator_base
* __old
= __iter
;
96 __iter
= __iter
->_M_next
;
100 } // anonymous namespace
102 namespace __gnu_debug
104 const char* _S_debug_messages
[] =
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",
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;)",
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",
162 "attempt to dereference an end-of-stream istream_iterator",
163 "attempt to increment an end-of-stream istream_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",
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"
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 "attempt to insert with an iterator range [%1.name;, %2.name;) from this container"
189 _Safe_sequence_base::
192 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
193 detach_all(_M_iterators
);
196 detach_all(_M_const_iterators
);
197 _M_const_iterators
= 0;
201 _Safe_sequence_base::
204 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
205 for (_Safe_iterator_base
* __iter
= _M_iterators
; __iter
;)
207 _Safe_iterator_base
* __old
= __iter
;
208 __iter
= __iter
->_M_next
;
209 if (__old
->_M_singular())
210 __old
->_M_detach_single();
213 for (_Safe_iterator_base
* __iter2
= _M_const_iterators
; __iter2
;)
215 _Safe_iterator_base
* __old
= __iter2
;
216 __iter2
= __iter2
->_M_next
;
217 if (__old
->_M_singular())
218 __old
->_M_detach_single();
223 _Safe_sequence_base::
224 _M_revalidate_singular()
226 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
227 for (_Safe_iterator_base
* __iter
= _M_iterators
; __iter
;
228 __iter
= __iter
->_M_next
)
229 __iter
->_M_version
= _M_version
;
231 for (_Safe_iterator_base
* __iter2
= _M_const_iterators
; __iter2
;
232 __iter2
= __iter2
->_M_next
)
233 __iter2
->_M_version
= _M_version
;
237 _Safe_sequence_base::
238 _M_swap(_Safe_sequence_base
& __x
) noexcept
240 // We need to lock both sequences to swap
241 using namespace __gnu_cxx
;
242 __mutex
*__this_mutex
= &_M_get_mutex();
243 __mutex
*__x_mutex
= &__x
._M_get_mutex();
244 if (__this_mutex
== __x_mutex
)
246 __scoped_lock
__lock(*__this_mutex
);
247 swap_seq(*this, __x
);
251 __scoped_lock
__l1(__this_mutex
< __x_mutex
252 ? *__this_mutex
: *__x_mutex
);
253 __scoped_lock
__l2(__this_mutex
< __x_mutex
254 ? *__x_mutex
: *__this_mutex
);
255 swap_seq(*this, __x
);
260 _Safe_sequence_base::
261 _M_get_mutex() throw ()
262 { return get_safe_base_mutex(this); }
265 _Safe_sequence_base::
266 _M_attach(_Safe_iterator_base
* __it
, bool __constant
)
268 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
269 _M_attach_single(__it
, __constant
);
273 _Safe_sequence_base::
274 _M_attach_single(_Safe_iterator_base
* __it
, bool __constant
) throw ()
276 _Safe_iterator_base
*& __its
=
277 __constant
? _M_const_iterators
: _M_iterators
;
278 __it
->_M_next
= __its
;
280 __it
->_M_next
->_M_prior
= __it
;
285 _Safe_sequence_base::
286 _M_detach(_Safe_iterator_base
* __it
)
288 // Remove __it from this sequence's list
289 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
290 _M_detach_single(__it
);
294 _Safe_sequence_base::
295 _M_detach_single(_Safe_iterator_base
* __it
) throw ()
297 // Remove __it from this sequence's list
299 if (_M_const_iterators
== __it
)
300 _M_const_iterators
= __it
->_M_next
;
301 if (_M_iterators
== __it
)
302 _M_iterators
= __it
->_M_next
;
306 _Safe_iterator_base::
307 _M_attach(_Safe_sequence_base
* __seq
, bool __constant
)
311 // Attach to the new sequence (if there is one)
315 _M_version
= _M_sequence
->_M_version
;
316 _M_sequence
->_M_attach(this, __constant
);
321 _Safe_iterator_base::
322 _M_attach_single(_Safe_sequence_base
* __seq
, bool __constant
) throw ()
326 // Attach to the new sequence (if there is one)
330 _M_version
= _M_sequence
->_M_version
;
331 _M_sequence
->_M_attach_single(this, __constant
);
336 _Safe_iterator_base::
340 _M_sequence
->_M_detach(this);
346 _Safe_iterator_base::
347 _M_detach_single() throw ()
350 _M_sequence
->_M_detach_single(this);
356 _Safe_iterator_base::
366 _Safe_iterator_base::
367 _M_singular() const throw ()
368 { return !_M_sequence
|| _M_version
!= _M_sequence
->_M_version
; }
371 _Safe_iterator_base::
372 _M_can_compare(const _Safe_iterator_base
& __x
) const throw ()
374 return (!_M_singular()
375 && !__x
._M_singular() && _M_sequence
== __x
._M_sequence
);
379 _Safe_iterator_base::
380 _M_get_mutex() throw ()
381 { return get_safe_base_mutex(_M_sequence
); }
383 _Safe_unordered_container_base
*
384 _Safe_local_iterator_base::
385 _M_get_container() const noexcept
386 { return static_cast<_Safe_unordered_container_base
*>(_M_sequence
); }
389 _Safe_local_iterator_base::
390 _M_attach(_Safe_sequence_base
* __cont
, bool __constant
)
394 // Attach to the new container (if there is one)
397 _M_sequence
= __cont
;
398 _M_version
= _M_sequence
->_M_version
;
399 _M_get_container()->_M_attach_local(this, __constant
);
404 _Safe_local_iterator_base::
405 _M_attach_single(_Safe_sequence_base
* __cont
, bool __constant
) throw ()
409 // Attach to the new container (if there is one)
412 _M_sequence
= __cont
;
413 _M_version
= _M_sequence
->_M_version
;
414 _M_get_container()->_M_attach_local_single(this, __constant
);
419 _Safe_local_iterator_base::
423 _M_get_container()->_M_detach_local(this);
429 _Safe_local_iterator_base::
430 _M_detach_single() throw ()
433 _M_get_container()->_M_detach_local_single(this);
439 _Safe_unordered_container_base::
442 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
443 detach_all(_M_iterators
);
446 detach_all(_M_const_iterators
);
447 _M_const_iterators
= 0;
449 detach_all(_M_local_iterators
);
450 _M_local_iterators
= 0;
452 detach_all(_M_const_local_iterators
);
453 _M_const_local_iterators
= 0;
457 _Safe_unordered_container_base::
458 _M_swap(_Safe_unordered_container_base
& __x
) noexcept
460 // We need to lock both containers to swap
461 using namespace __gnu_cxx
;
462 __mutex
*__this_mutex
= &_M_get_mutex();
463 __mutex
*__x_mutex
= &__x
._M_get_mutex();
464 if (__this_mutex
== __x_mutex
)
466 __scoped_lock
__lock(*__this_mutex
);
467 swap_ucont(*this, __x
);
471 __scoped_lock
__l1(__this_mutex
< __x_mutex
472 ? *__this_mutex
: *__x_mutex
);
473 __scoped_lock
__l2(__this_mutex
< __x_mutex
474 ? *__x_mutex
: *__this_mutex
);
475 swap_ucont(*this, __x
);
480 _Safe_unordered_container_base::
481 _M_attach_local(_Safe_iterator_base
* __it
, bool __constant
)
483 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
484 _M_attach_local_single(__it
, __constant
);
488 _Safe_unordered_container_base::
489 _M_attach_local_single(_Safe_iterator_base
* __it
, bool __constant
) throw ()
491 _Safe_iterator_base
*& __its
=
492 __constant
? _M_const_local_iterators
: _M_local_iterators
;
493 __it
->_M_next
= __its
;
495 __it
->_M_next
->_M_prior
= __it
;
500 _Safe_unordered_container_base::
501 _M_detach_local(_Safe_iterator_base
* __it
)
503 // Remove __it from this container's list
504 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
505 _M_detach_local_single(__it
);
509 _Safe_unordered_container_base::
510 _M_detach_local_single(_Safe_iterator_base
* __it
) throw ()
512 // Remove __it from this container's list
514 if (_M_const_local_iterators
== __it
)
515 _M_const_local_iterators
= __it
->_M_next
;
516 if (_M_local_iterators
== __it
)
517 _M_local_iterators
= __it
->_M_next
;
521 _Error_formatter::_Parameter::
522 _M_print_field(const _Error_formatter
* __formatter
, const char* __name
) const
524 assert(this->_M_kind
!= _Parameter::__unused_param
);
525 const int __bufsize
= 64;
526 char __buf
[__bufsize
];
528 if (_M_kind
== __iterator
)
530 if (strcmp(__name
, "name") == 0)
532 assert(_M_variant
._M_iterator
._M_name
);
533 __formatter
->_M_print_word(_M_variant
._M_iterator
._M_name
);
535 else if (strcmp(__name
, "address") == 0)
537 __formatter
->_M_format_word(__buf
, __bufsize
, "%p",
538 _M_variant
._M_iterator
._M_address
);
539 __formatter
->_M_print_word(__buf
);
541 else if (strcmp(__name
, "type") == 0)
543 if (!_M_variant
._M_iterator
._M_type
)
544 __formatter
->_M_print_word("<unknown type>");
547 __formatter
->_M_print_word(_M_variant
._M_iterator
.
550 else if (strcmp(__name
, "constness") == 0)
552 static const char* __constness_names
[__last_constness
] =
558 __formatter
->_M_print_word(__constness_names
[_M_variant
.
562 else if (strcmp(__name
, "state") == 0)
564 static const char* __state_names
[__last_state
] =
568 "dereferenceable (start-of-sequence)",
573 __formatter
->_M_print_word(__state_names
[_M_variant
.
574 _M_iterator
._M_state
]);
576 else if (strcmp(__name
, "sequence") == 0)
578 assert(_M_variant
._M_iterator
._M_sequence
);
579 __formatter
->_M_format_word(__buf
, __bufsize
, "%p",
580 _M_variant
._M_iterator
._M_sequence
);
581 __formatter
->_M_print_word(__buf
);
583 else if (strcmp(__name
, "seq_type") == 0)
585 if (!_M_variant
._M_iterator
._M_seq_type
)
586 __formatter
->_M_print_word("<unknown seq_type>");
589 __formatter
->_M_print_word(_M_variant
._M_iterator
.
590 _M_seq_type
->name());
595 else if (_M_kind
== __sequence
)
597 if (strcmp(__name
, "name") == 0)
599 assert(_M_variant
._M_sequence
._M_name
);
600 __formatter
->_M_print_word(_M_variant
._M_sequence
._M_name
);
602 else if (strcmp(__name
, "address") == 0)
604 assert(_M_variant
._M_sequence
._M_address
);
605 __formatter
->_M_format_word(__buf
, __bufsize
, "%p",
606 _M_variant
._M_sequence
._M_address
);
607 __formatter
->_M_print_word(__buf
);
609 else if (strcmp(__name
, "type") == 0)
611 if (!_M_variant
._M_sequence
._M_type
)
612 __formatter
->_M_print_word("<unknown type>");
615 __formatter
->_M_print_word(_M_variant
._M_sequence
.
621 else if (_M_kind
== __integer
)
623 if (strcmp(__name
, "name") == 0)
625 assert(_M_variant
._M_integer
._M_name
);
626 __formatter
->_M_print_word(_M_variant
._M_integer
._M_name
);
631 else if (_M_kind
== __string
)
633 if (strcmp(__name
, "name") == 0)
635 assert(_M_variant
._M_string
._M_name
);
636 __formatter
->_M_print_word(_M_variant
._M_string
._M_name
);
648 _Error_formatter::_Parameter::
649 _M_print_description(const _Error_formatter
* __formatter
) const
651 const int __bufsize
= 128;
652 char __buf
[__bufsize
];
654 if (_M_kind
== __iterator
)
656 __formatter
->_M_print_word("iterator ");
657 if (_M_variant
._M_iterator
._M_name
)
659 __formatter
->_M_format_word(__buf
, __bufsize
, "\"%s\" ",
660 _M_variant
._M_iterator
._M_name
);
661 __formatter
->_M_print_word(__buf
);
664 __formatter
->_M_format_word(__buf
, __bufsize
, "@ 0x%p {\n",
665 _M_variant
._M_iterator
._M_address
);
666 __formatter
->_M_print_word(__buf
);
667 if (_M_variant
._M_iterator
._M_type
)
669 __formatter
->_M_print_word("type = ");
670 _M_print_field(__formatter
, "type");
672 if (_M_variant
._M_iterator
._M_constness
!= __unknown_constness
)
674 __formatter
->_M_print_word(" (");
675 _M_print_field(__formatter
, "constness");
676 __formatter
->_M_print_word(" iterator)");
678 __formatter
->_M_print_word(";\n");
681 if (_M_variant
._M_iterator
._M_state
!= __unknown_state
)
683 __formatter
->_M_print_word(" state = ");
684 _M_print_field(__formatter
, "state");
685 __formatter
->_M_print_word(";\n");
688 if (_M_variant
._M_iterator
._M_sequence
)
690 __formatter
->_M_print_word(" references sequence ");
691 if (_M_variant
._M_iterator
._M_seq_type
)
693 __formatter
->_M_print_word("with type `");
694 _M_print_field(__formatter
, "seq_type");
695 __formatter
->_M_print_word("' ");
698 __formatter
->_M_format_word(__buf
, __bufsize
, "@ 0x%p\n",
699 _M_variant
._M_iterator
._M_sequence
);
700 __formatter
->_M_print_word(__buf
);
702 __formatter
->_M_print_word("}\n");
704 else if (_M_kind
== __sequence
)
706 __formatter
->_M_print_word("sequence ");
707 if (_M_variant
._M_sequence
._M_name
)
709 __formatter
->_M_format_word(__buf
, __bufsize
, "\"%s\" ",
710 _M_variant
._M_sequence
._M_name
);
711 __formatter
->_M_print_word(__buf
);
714 __formatter
->_M_format_word(__buf
, __bufsize
, "@ 0x%p {\n",
715 _M_variant
._M_sequence
._M_address
);
716 __formatter
->_M_print_word(__buf
);
718 if (_M_variant
._M_sequence
._M_type
)
720 __formatter
->_M_print_word(" type = ");
721 _M_print_field(__formatter
, "type");
722 __formatter
->_M_print_word(";\n");
724 __formatter
->_M_print_word("}\n");
728 const _Error_formatter
&
729 _Error_formatter::_M_message(_Debug_msg_id __id
) const throw ()
730 { return this->_M_message(_S_debug_messages
[__id
]); }
733 _Error_formatter::_M_error() const
735 const int __bufsize
= 128;
736 char __buf
[__bufsize
];
738 // Emit file & line number information
743 _M_format_word(__buf
, __bufsize
, "%s:", _M_file
);
744 _M_print_word(__buf
);
745 _M_column
+= strlen(__buf
);
750 _M_format_word(__buf
, __bufsize
, "%u:", _M_line
);
751 _M_print_word(__buf
);
752 _M_column
+= strlen(__buf
);
757 _M_print_word("error: ");
759 // Print the error message
761 _M_print_string(_M_text
);
762 _M_print_word(".\n");
764 // Emit descriptions of the objects involved in the operation
766 bool __has_noninteger_parameters
= false;
767 for (unsigned int __i
= 0; __i
< _M_num_parameters
; ++__i
)
769 if (_M_parameters
[__i
]._M_kind
== _Parameter::__iterator
770 || _M_parameters
[__i
]._M_kind
== _Parameter::__sequence
)
772 if (!__has_noninteger_parameters
)
774 _M_first_line
= true;
775 _M_print_word("\nObjects involved in the operation:\n");
776 __has_noninteger_parameters
= true;
778 _M_parameters
[__i
]._M_print_description(this);
785 template<typename _Tp
>
787 _Error_formatter::_M_format_word(char* __buf
,
788 int __n
__attribute__ ((__unused__
)),
789 const char* __fmt
, _Tp __s
) const throw ()
791 #ifdef _GLIBCXX_USE_C99
792 std::snprintf(__buf
, __n
, __fmt
, __s
);
794 std::sprintf(__buf
, __fmt
, __s
);
800 _Error_formatter::_M_print_word(const char* __word
) const
804 fprintf(stderr
, "%s", __word
);
808 size_t __length
= strlen(__word
);
812 size_t __visual_length
813 = __word
[__length
- 1] == '\n' ? __length
- 1 : __length
;
814 if (__visual_length
== 0
815 || (_M_column
+ __visual_length
< _M_max_length
)
816 || (__visual_length
>= _M_max_length
&& _M_column
== 1))
818 // If this isn't the first line, indent
819 if (_M_column
== 1 && !_M_first_line
)
821 char __spacing
[_M_indent
+ 1];
822 for (int i
= 0; i
< _M_indent
; ++i
)
824 __spacing
[_M_indent
] = '\0';
825 fprintf(stderr
, "%s", __spacing
);
826 _M_column
+= _M_indent
;
829 fprintf(stderr
, "%s", __word
);
831 if (__word
[__length
- 1] == '\n')
833 _M_first_line
= false;
837 _M_column
+= __length
;
842 _M_print_word(__word
);
848 _M_print_string(const char* __string
) const
850 const char* __start
= __string
;
851 const char* __finish
= __start
;
852 const int __bufsize
= 128;
853 char __buf
[__bufsize
];
859 // [__start, __finish) denotes the next word
861 while (isalnum(*__finish
))
863 if (__start
== __finish
)
865 if (isspace(*__finish
))
868 const ptrdiff_t __len
= __finish
- __start
;
869 assert(__len
< __bufsize
);
870 memcpy(__buf
, __start
, __len
);
872 _M_print_word(__buf
);
875 // Skip extra whitespace
876 while (*__start
== ' ')
891 // Get the parameter number
892 assert(*__start
>= '1' && *__start
<= '9');
893 size_t __param
= *__start
- '0';
895 assert(__param
< _M_num_parameters
);
897 // '.' separates the parameter number from the field
898 // name, if there is one.
902 assert(*__start
== ';');
905 if (_M_parameters
[__param
]._M_kind
== _Parameter::__integer
)
907 _M_format_word(__buf
, __bufsize
, "%ld",
908 _M_parameters
[__param
]._M_variant
._M_integer
._M_value
);
909 _M_print_word(__buf
);
911 else if (_M_parameters
[__param
]._M_kind
== _Parameter::__string
)
912 _M_print_string(_M_parameters
[__param
]._M_variant
._M_string
._M_value
);
916 // Extract the field name we want
917 enum { __max_field_len
= 16 };
918 char __field
[__max_field_len
];
921 while (*__start
!= ';')
924 assert(__field_idx
< __max_field_len
-1);
925 __field
[__field_idx
++] = *__start
++;
928 __field
[__field_idx
] = 0;
930 _M_parameters
[__param
]._M_print_field(this, __field
);
935 _Error_formatter::_M_get_max_length() const throw ()
937 const char* __nptr
= std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
941 const unsigned long __ret
= std::strtoul(__nptr
, &__endptr
, 0);
942 if (*__nptr
!= '\0' && *__endptr
== '\0')
943 _M_max_length
= __ret
;
950 _Error_formatter::_M_format_word(char*, int, const char*,
955 _Error_formatter::_M_format_word(char*, int, const char*, long) const;
959 _Error_formatter::_M_format_word(char*, int, const char*,
964 _Error_formatter::_M_format_word(char*, int, const char*,
966 } // namespace __gnu_debug