1 // Debugging mode support code -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
4 // 2011 Free Software Foundation, Inc.
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)
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>
43 /** Returns different instances of __mutex depending on the passed address
44 * in order to limit contention without breaking current library binary
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
];
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
;
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
);
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
);
92 detach_all(__gnu_debug::_Safe_iterator_base
* __iter
)
96 __gnu_debug::_Safe_iterator_base
* __old
= __iter
;
97 __iter
= __iter
->_M_next
;
101 } // anonymous namespace
103 namespace __gnu_debug
105 const char* _S_debug_messages
[] =
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",
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;)",
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",
163 "attempt to dereference an end-of-stream istream_iterator",
164 "attempt to increment an end-of-stream istream_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",
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"
180 "function requires a non-empty iterator range [%1.name;, %2.name;)"
184 _Safe_sequence_base::
187 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
188 detach_all(_M_iterators
);
191 detach_all(_M_const_iterators
);
192 _M_const_iterators
= 0;
196 _Safe_sequence_base::
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();
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
;
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
);
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
);
255 _Safe_sequence_base::
256 _M_get_mutex() throw ()
257 { return get_safe_base_mutex(this); }
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
);
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
;
275 __it
->_M_next
->_M_prior
= __it
;
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
);
289 _Safe_sequence_base::
290 _M_detach_single(_Safe_iterator_base
* __it
) throw ()
292 // Remove __it from this sequence's list
294 if (_M_const_iterators
== __it
)
295 _M_const_iterators
= __it
->_M_next
;
296 if (_M_iterators
== __it
)
297 _M_iterators
= __it
->_M_next
;
301 _Safe_iterator_base::
302 _M_attach(_Safe_sequence_base
* __seq
, bool __constant
)
306 // Attach to the new sequence (if there is one)
310 _M_version
= _M_sequence
->_M_version
;
311 _M_sequence
->_M_attach(this, __constant
);
316 _Safe_iterator_base::
317 _M_attach_single(_Safe_sequence_base
* __seq
, bool __constant
) throw ()
321 // Attach to the new sequence (if there is one)
325 _M_version
= _M_sequence
->_M_version
;
326 _M_sequence
->_M_attach_single(this, __constant
);
331 _Safe_iterator_base::
335 _M_sequence
->_M_detach(this);
341 _Safe_iterator_base::
342 _M_detach_single() throw ()
345 _M_sequence
->_M_detach_single(this);
351 _Safe_iterator_base::
361 _Safe_iterator_base::
362 _M_singular() const throw ()
363 { return !_M_sequence
|| _M_version
!= _M_sequence
->_M_version
; }
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
);
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
); }
384 _Safe_local_iterator_base::
385 _M_attach(_Safe_sequence_base
* __cont
, bool __constant
)
389 // Attach to the new container (if there is one)
392 _M_sequence
= __cont
;
393 _M_version
= _M_sequence
->_M_version
;
394 _M_get_container()->_M_attach_local(this, __constant
);
399 _Safe_local_iterator_base::
400 _M_attach_single(_Safe_sequence_base
* __cont
, bool __constant
) throw ()
404 // Attach to the new container (if there is one)
407 _M_sequence
= __cont
;
408 _M_version
= _M_sequence
->_M_version
;
409 _M_get_container()->_M_attach_local_single(this, __constant
);
414 _Safe_local_iterator_base::
418 _M_get_container()->_M_detach_local(this);
424 _Safe_local_iterator_base::
425 _M_detach_single() throw ()
428 _M_get_container()->_M_detach_local_single(this);
434 _Safe_unordered_container_base::
437 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
438 detach_all(_M_iterators
);
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;
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
);
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
);
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
);
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
;
490 __it
->_M_next
->_M_prior
= __it
;
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
);
504 _Safe_unordered_container_base::
505 _M_detach_local_single(_Safe_iterator_base
* __it
) throw ()
507 // Remove __it from this container's list
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
;
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>");
542 __formatter
->_M_print_word(_M_variant
._M_iterator
.
545 else if (strcmp(__name
, "constness") == 0)
547 static const char* __constness_names
[__last_constness
] =
553 __formatter
->_M_print_word(__constness_names
[_M_variant
.
557 else if (strcmp(__name
, "state") == 0)
559 static const char* __state_names
[__last_state
] =
563 "dereferenceable (start-of-sequence)",
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>");
584 __formatter
->_M_print_word(_M_variant
._M_iterator
.
585 _M_seq_type
->name());
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>");
610 __formatter
->_M_print_word(_M_variant
._M_sequence
.
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
);
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
);
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
]); }
728 _Error_formatter::_M_error() const
730 const int __bufsize
= 128;
731 char __buf
[__bufsize
];
733 // Emit file & line number information
738 _M_format_word(__buf
, __bufsize
, "%s:", _M_file
);
739 _M_print_word(__buf
);
740 _M_column
+= strlen(__buf
);
745 _M_format_word(__buf
, __bufsize
, "%u:", _M_line
);
746 _M_print_word(__buf
);
747 _M_column
+= strlen(__buf
);
752 _M_print_word("error: ");
754 // Print the error message
756 _M_print_string(_M_text
);
757 _M_print_word(".\n");
759 // Emit descriptions of the objects involved in the operation
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);
780 template<typename _Tp
>
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
);
789 std::sprintf(__buf
, __fmt
, __s
);
795 _Error_formatter::_M_print_word(const char* __word
) const
799 fprintf(stderr
, "%s", __word
);
803 size_t __length
= strlen(__word
);
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
)
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;
834 _M_print_word(__word
);
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
];
851 // [__start, __finish) denotes the next word
853 while (isalnum(*__finish
))
855 if (__start
== __finish
)
857 if (isspace(*__finish
))
860 const ptrdiff_t __len
= __finish
- __start
;
861 assert(__len
< __bufsize
);
862 memcpy(__buf
, __start
, __len
);
864 _M_print_word(__buf
);
867 // Skip extra whitespace
868 while (*__start
== ' ')
883 // Get the parameter number
884 assert(*__start
>= '1' && *__start
<= '9');
885 size_t __param
= *__start
- '0';
887 assert(__param
< _M_num_parameters
);
889 // '.' separates the parameter number from the field
890 // name, if there is one.
894 assert(*__start
== ';');
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
);
908 // Extract the field name we want
909 enum { __max_field_len
= 16 };
910 char __field
[__max_field_len
];
913 while (*__start
!= ';')
916 assert(__field_idx
< __max_field_len
-1);
917 __field
[__field_idx
++] = *__start
++;
920 __field
[__field_idx
] = 0;
922 _M_parameters
[__param
]._M_print_field(this, __field
);
927 _Error_formatter::_M_get_max_length() const throw ()
929 const char* __nptr
= std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
933 const unsigned long __ret
= std::strtoul(__nptr
, &__endptr
, 0);
934 if (*__nptr
!= '\0' && *__endptr
== '\0')
935 _M_max_length
= __ret
;
942 _Error_formatter::_M_format_word(char*, int, const char*,
947 _Error_formatter::_M_format_word(char*, int, const char*, long) const;
951 _Error_formatter::_M_format_word(char*, int, const char*,
956 _Error_formatter::_M_format_word(char*, int, const char*,
958 } // namespace __gnu_debug