xref: /freebsd-12.1/contrib/libstdc++/src/debug.cc (revision f8a1b7d9)
1ffeaf689SAlexander Kabaev // Debugging mode support code -*- C++ -*-
2ffeaf689SAlexander Kabaev 
3*f8a1b7d9SAlexander Kabaev // Copyright (C) 2003, 2004, 2005, 2006
4ffeaf689SAlexander Kabaev // Free Software Foundation, Inc.
5ffeaf689SAlexander Kabaev //
6ffeaf689SAlexander Kabaev // This file is part of the GNU ISO C++ Library.  This library is free
7ffeaf689SAlexander Kabaev // software; you can redistribute it and/or modify it under the
8ffeaf689SAlexander Kabaev // terms of the GNU General Public License as published by the
9ffeaf689SAlexander Kabaev // Free Software Foundation; either version 2, or (at your option)
10ffeaf689SAlexander Kabaev // any later version.
11ffeaf689SAlexander Kabaev 
12ffeaf689SAlexander Kabaev // This library is distributed in the hope that it will be useful,
13ffeaf689SAlexander Kabaev // but WITHOUT ANY WARRANTY; without even the implied warranty of
14ffeaf689SAlexander Kabaev // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15ffeaf689SAlexander Kabaev // GNU General Public License for more details.
16ffeaf689SAlexander Kabaev 
17ffeaf689SAlexander Kabaev // You should have received a copy of the GNU General Public License along
18ffeaf689SAlexander Kabaev // with this library; see the file COPYING.  If not, write to the Free
19*f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20ffeaf689SAlexander Kabaev // USA.
21ffeaf689SAlexander Kabaev 
22ffeaf689SAlexander Kabaev // As a special exception, you may use this file as part of a free software
23ffeaf689SAlexander Kabaev // library without restriction.  Specifically, if other files instantiate
24ffeaf689SAlexander Kabaev // templates or use macros or inline functions from this file, or you compile
25ffeaf689SAlexander Kabaev // this file and link it with other files to produce an executable, this
26ffeaf689SAlexander Kabaev // file does not by itself cause the resulting executable to be covered by
27ffeaf689SAlexander Kabaev // the GNU General Public License.  This exception does not however
28ffeaf689SAlexander Kabaev // invalidate any other reasons why the executable file might be covered by
29ffeaf689SAlexander Kabaev // the GNU General Public License.
30ffeaf689SAlexander Kabaev 
31ffeaf689SAlexander Kabaev #include <debug/debug.h>
32ffeaf689SAlexander Kabaev #include <debug/safe_sequence.h>
33ffeaf689SAlexander Kabaev #include <debug/safe_iterator.h>
34ffeaf689SAlexander Kabaev #include <algorithm>
35ffeaf689SAlexander Kabaev #include <cassert>
36ffeaf689SAlexander Kabaev #include <cstring>
37ffeaf689SAlexander Kabaev #include <cctype>
38ffeaf689SAlexander Kabaev 
39ffeaf689SAlexander Kabaev using namespace std;
40ffeaf689SAlexander Kabaev 
41*f8a1b7d9SAlexander Kabaev namespace
42f260e61bSAlexander Kabaev {
43*f8a1b7d9SAlexander Kabaev   __gnu_cxx::__mutex safe_base_mutex;
44*f8a1b7d9SAlexander Kabaev } // anonymous namespace
45f260e61bSAlexander Kabaev 
46ffeaf689SAlexander Kabaev namespace __gnu_debug
47ffeaf689SAlexander Kabaev {
48ffeaf689SAlexander Kabaev   const char* _S_debug_messages[] =
49ffeaf689SAlexander Kabaev   {
50ffeaf689SAlexander Kabaev     "function requires a valid iterator range [%1.name;, %2.name;)",
51ffeaf689SAlexander Kabaev     "attempt to insert into container with a singular iterator",
52ffeaf689SAlexander Kabaev     "attempt to insert into container with an iterator"
53ffeaf689SAlexander Kabaev     " from a different container",
54ffeaf689SAlexander Kabaev     "attempt to erase from container with a %2.state; iterator",
55ffeaf689SAlexander Kabaev     "attempt to erase from container with an iterator"
56ffeaf689SAlexander Kabaev     " from a different container",
57ffeaf689SAlexander Kabaev     "attempt to subscript container with out-of-bounds index %2;,"
58ffeaf689SAlexander Kabaev     " but container only holds %3; elements",
59ffeaf689SAlexander Kabaev     "attempt to access an element in an empty container",
60ffeaf689SAlexander Kabaev     "elements in iterator range [%1.name;, %2.name;)"
61ffeaf689SAlexander Kabaev     " are not partitioned by the value %3;",
62ffeaf689SAlexander Kabaev     "elements in iterator range [%1.name;, %2.name;)"
63ffeaf689SAlexander Kabaev     " are not partitioned by the predicate %3; and value %4;",
64ffeaf689SAlexander Kabaev     "elements in iterator range [%1.name;, %2.name;) are not sorted",
65ffeaf689SAlexander Kabaev     "elements in iterator range [%1.name;, %2.name;)"
66ffeaf689SAlexander Kabaev     " are not sorted according to the predicate %3;",
67ffeaf689SAlexander Kabaev     "elements in iterator range [%1.name;, %2.name;) do not form a heap",
68ffeaf689SAlexander Kabaev     "elements in iterator range [%1.name;, %2.name;)"
69ffeaf689SAlexander Kabaev     " do not form a heap with respect to the predicate %3;",
70ffeaf689SAlexander Kabaev     "attempt to write through a singular bitset reference",
71ffeaf689SAlexander Kabaev     "attempt to read from a singular bitset reference",
72ffeaf689SAlexander Kabaev     "attempt to flip a singular bitset reference",
73ffeaf689SAlexander Kabaev     "attempt to splice a list into itself",
74ffeaf689SAlexander Kabaev     "attempt to splice lists with inequal allocators",
75ffeaf689SAlexander Kabaev     "attempt to splice elements referenced by a %1.state; iterator",
76ffeaf689SAlexander Kabaev     "attempt to splice an iterator from a different container",
77ffeaf689SAlexander Kabaev     "splice destination %1.name;"
78ffeaf689SAlexander Kabaev     " occurs within source range [%2.name;, %3.name;)",
79ffeaf689SAlexander Kabaev     "attempt to initialize an iterator that will immediately become singular",
80ffeaf689SAlexander Kabaev     "attempt to copy-construct an iterator from a singular iterator",
81ffeaf689SAlexander Kabaev     "attempt to construct a constant iterator"
82ffeaf689SAlexander Kabaev     " from a singular mutable iterator",
83ffeaf689SAlexander Kabaev     "attempt to copy from a singular iterator",
84ffeaf689SAlexander Kabaev     "attempt to dereference a %1.state; iterator",
85ffeaf689SAlexander Kabaev     "attempt to increment a %1.state; iterator",
86ffeaf689SAlexander Kabaev     "attempt to decrement a %1.state; iterator",
87ffeaf689SAlexander Kabaev     "attempt to subscript a %1.state; iterator %2; step from"
88ffeaf689SAlexander Kabaev     " its current position, which falls outside its dereferenceable range",
89ffeaf689SAlexander Kabaev     "attempt to advance a %1.state; iterator %2; steps,"
90ffeaf689SAlexander Kabaev     " which falls outside its valid range",
91ffeaf689SAlexander Kabaev     "attempt to retreat a %1.state; iterator %2; steps,"
92ffeaf689SAlexander Kabaev     " which falls outside its valid range",
93ffeaf689SAlexander Kabaev     "attempt to compare a %1.state; iterator to a %2.state; iterator",
94ffeaf689SAlexander Kabaev     "attempt to compare iterators from different sequences",
95ffeaf689SAlexander Kabaev     "attempt to order a %1.state; iterator to a %2.state; iterator",
96ffeaf689SAlexander Kabaev     "attempt to order iterators from different sequences",
97ffeaf689SAlexander Kabaev     "attempt to compute the difference between a %1.state;"
98ffeaf689SAlexander Kabaev     " iterator to a %2.state; iterator",
99ffeaf689SAlexander Kabaev     "attempt to compute the different between two iterators"
100ffeaf689SAlexander Kabaev     " from different sequences",
101ffeaf689SAlexander Kabaev     "attempt to dereference an end-of-stream istream_iterator",
102ffeaf689SAlexander Kabaev     "attempt to increment an end-of-stream istream_iterator",
103ffeaf689SAlexander Kabaev     "attempt to output via an ostream_iterator with no associated stream",
104ffeaf689SAlexander Kabaev     "attempt to dereference an end-of-stream istreambuf_iterator"
105ffeaf689SAlexander Kabaev     " (this is a GNU extension)",
106ffeaf689SAlexander Kabaev     "attempt to increment an end-of-stream istreambuf_iterator"
107ffeaf689SAlexander Kabaev   };
108ffeaf689SAlexander Kabaev 
109ffeaf689SAlexander Kabaev   void
110ffeaf689SAlexander Kabaev   _Safe_sequence_base::
_M_detach_all()111ffeaf689SAlexander Kabaev   _M_detach_all()
112ffeaf689SAlexander Kabaev   {
113*f8a1b7d9SAlexander Kabaev     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
114ffeaf689SAlexander Kabaev     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
115ffeaf689SAlexander Kabaev       {
116ffeaf689SAlexander Kabaev 	_Safe_iterator_base* __old = __iter;
117ffeaf689SAlexander Kabaev 	__iter = __iter->_M_next;
118*f8a1b7d9SAlexander Kabaev 	__old->_M_detach_single();
119ffeaf689SAlexander Kabaev       }
120ffeaf689SAlexander Kabaev 
121ffeaf689SAlexander Kabaev     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
122ffeaf689SAlexander Kabaev       {
123ffeaf689SAlexander Kabaev 	_Safe_iterator_base* __old = __iter2;
124ffeaf689SAlexander Kabaev 	__iter2 = __iter2->_M_next;
125*f8a1b7d9SAlexander Kabaev 	__old->_M_detach_single();
126ffeaf689SAlexander Kabaev       }
127ffeaf689SAlexander Kabaev   }
128ffeaf689SAlexander Kabaev 
129ffeaf689SAlexander Kabaev   void
130ffeaf689SAlexander Kabaev   _Safe_sequence_base::
_M_detach_singular()131ffeaf689SAlexander Kabaev   _M_detach_singular()
132ffeaf689SAlexander Kabaev   {
133*f8a1b7d9SAlexander Kabaev     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
134ffeaf689SAlexander Kabaev     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
135ffeaf689SAlexander Kabaev       {
136ffeaf689SAlexander Kabaev 	_Safe_iterator_base* __old = __iter;
137ffeaf689SAlexander Kabaev 	__iter = __iter->_M_next;
138ffeaf689SAlexander Kabaev 	if (__old->_M_singular())
139*f8a1b7d9SAlexander Kabaev 	  __old->_M_detach_single();
140ffeaf689SAlexander Kabaev       }
141ffeaf689SAlexander Kabaev 
142ffeaf689SAlexander Kabaev     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
143ffeaf689SAlexander Kabaev       {
144ffeaf689SAlexander Kabaev 	_Safe_iterator_base* __old = __iter2;
145ffeaf689SAlexander Kabaev 	__iter2 = __iter2->_M_next;
146ffeaf689SAlexander Kabaev 	if (__old->_M_singular())
147*f8a1b7d9SAlexander Kabaev 	  __old->_M_detach_single();
148ffeaf689SAlexander Kabaev       }
149ffeaf689SAlexander Kabaev   }
150ffeaf689SAlexander Kabaev 
151ffeaf689SAlexander Kabaev   void
152ffeaf689SAlexander Kabaev   _Safe_sequence_base::
_M_revalidate_singular()153ffeaf689SAlexander Kabaev   _M_revalidate_singular()
154ffeaf689SAlexander Kabaev   {
155*f8a1b7d9SAlexander Kabaev     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
156*f8a1b7d9SAlexander Kabaev     for (_Safe_iterator_base* __iter = _M_iterators; __iter;
157*f8a1b7d9SAlexander Kabaev 	 __iter = __iter->_M_next)
158ffeaf689SAlexander Kabaev       __iter->_M_version = _M_version;
159ffeaf689SAlexander Kabaev 
160*f8a1b7d9SAlexander Kabaev     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
161*f8a1b7d9SAlexander Kabaev 	 __iter2 = __iter2->_M_next)
162*f8a1b7d9SAlexander Kabaev       __iter2->_M_version = _M_version;
163ffeaf689SAlexander Kabaev   }
164ffeaf689SAlexander Kabaev 
165ffeaf689SAlexander Kabaev   void
166ffeaf689SAlexander Kabaev   _Safe_sequence_base::
_M_swap(_Safe_sequence_base & __x)167ffeaf689SAlexander Kabaev   _M_swap(_Safe_sequence_base& __x)
168ffeaf689SAlexander Kabaev   {
169*f8a1b7d9SAlexander Kabaev     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
170ffeaf689SAlexander Kabaev     swap(_M_iterators, __x._M_iterators);
171ffeaf689SAlexander Kabaev     swap(_M_const_iterators, __x._M_const_iterators);
172ffeaf689SAlexander Kabaev     swap(_M_version, __x._M_version);
173ffeaf689SAlexander Kabaev     _Safe_iterator_base* __iter;
174ffeaf689SAlexander Kabaev     for (__iter = _M_iterators; __iter; __iter = __iter->_M_next)
175ffeaf689SAlexander Kabaev       __iter->_M_sequence = this;
176ffeaf689SAlexander Kabaev     for (__iter = __x._M_iterators; __iter; __iter = __iter->_M_next)
177ffeaf689SAlexander Kabaev       __iter->_M_sequence = &__x;
178ffeaf689SAlexander Kabaev     for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next)
179ffeaf689SAlexander Kabaev       __iter->_M_sequence = this;
180ffeaf689SAlexander Kabaev     for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next)
181ffeaf689SAlexander Kabaev       __iter->_M_sequence = &__x;
182ffeaf689SAlexander Kabaev   }
183ffeaf689SAlexander Kabaev 
184*f8a1b7d9SAlexander Kabaev   __gnu_cxx::__mutex&
185*f8a1b7d9SAlexander Kabaev   _Safe_sequence_base::
_M_get_mutex()186*f8a1b7d9SAlexander Kabaev   _M_get_mutex()
187*f8a1b7d9SAlexander Kabaev   { return safe_base_mutex; }
188*f8a1b7d9SAlexander Kabaev 
189ffeaf689SAlexander Kabaev   void
190ffeaf689SAlexander Kabaev   _Safe_iterator_base::
_M_attach(_Safe_sequence_base * __seq,bool __constant)191ffeaf689SAlexander Kabaev   _M_attach(_Safe_sequence_base* __seq, bool __constant)
192ffeaf689SAlexander Kabaev   {
193*f8a1b7d9SAlexander Kabaev     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
194*f8a1b7d9SAlexander Kabaev     _M_attach_single(__seq, __constant);
195*f8a1b7d9SAlexander Kabaev   }
196*f8a1b7d9SAlexander Kabaev 
197*f8a1b7d9SAlexander Kabaev   void
198*f8a1b7d9SAlexander Kabaev   _Safe_iterator_base::
_M_attach_single(_Safe_sequence_base * __seq,bool __constant)199*f8a1b7d9SAlexander Kabaev   _M_attach_single(_Safe_sequence_base* __seq, bool __constant)
200*f8a1b7d9SAlexander Kabaev   {
201*f8a1b7d9SAlexander Kabaev     _M_detach_single();
202ffeaf689SAlexander Kabaev 
203ffeaf689SAlexander Kabaev     // Attach to the new sequence (if there is one)
204ffeaf689SAlexander Kabaev     if (__seq)
205ffeaf689SAlexander Kabaev       {
206ffeaf689SAlexander Kabaev 	_M_sequence = __seq;
207ffeaf689SAlexander Kabaev 	_M_version = _M_sequence->_M_version;
208ffeaf689SAlexander Kabaev 	_M_prior = 0;
209ffeaf689SAlexander Kabaev 	if (__constant)
210ffeaf689SAlexander Kabaev 	  {
211ffeaf689SAlexander Kabaev 	    _M_next = _M_sequence->_M_const_iterators;
212ffeaf689SAlexander Kabaev 	    if (_M_next)
213ffeaf689SAlexander Kabaev 	      _M_next->_M_prior = this;
214ffeaf689SAlexander Kabaev 	    _M_sequence->_M_const_iterators = this;
215ffeaf689SAlexander Kabaev 	  }
216ffeaf689SAlexander Kabaev 	else
217ffeaf689SAlexander Kabaev 	  {
218ffeaf689SAlexander Kabaev 	    _M_next = _M_sequence->_M_iterators;
219ffeaf689SAlexander Kabaev 	    if (_M_next)
220ffeaf689SAlexander Kabaev 	      _M_next->_M_prior = this;
221ffeaf689SAlexander Kabaev 	    _M_sequence->_M_iterators = this;
222ffeaf689SAlexander Kabaev 	  }
223ffeaf689SAlexander Kabaev       }
224ffeaf689SAlexander Kabaev   }
225ffeaf689SAlexander Kabaev 
226ffeaf689SAlexander Kabaev   void
227ffeaf689SAlexander Kabaev   _Safe_iterator_base::
_M_detach()228ffeaf689SAlexander Kabaev   _M_detach()
229ffeaf689SAlexander Kabaev   {
230*f8a1b7d9SAlexander Kabaev     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
231*f8a1b7d9SAlexander Kabaev     _M_detach_single();
232*f8a1b7d9SAlexander Kabaev   }
233*f8a1b7d9SAlexander Kabaev 
234*f8a1b7d9SAlexander Kabaev   void
235*f8a1b7d9SAlexander Kabaev   _Safe_iterator_base::
_M_detach_single()236*f8a1b7d9SAlexander Kabaev   _M_detach_single()
237*f8a1b7d9SAlexander Kabaev   {
238ffeaf689SAlexander Kabaev     if (_M_sequence)
239ffeaf689SAlexander Kabaev       {
240ffeaf689SAlexander Kabaev 	// Remove us from this sequence's list
241ffeaf689SAlexander Kabaev 	if (_M_prior)
242ffeaf689SAlexander Kabaev 	  _M_prior->_M_next = _M_next;
243ffeaf689SAlexander Kabaev 	if (_M_next)
244ffeaf689SAlexander Kabaev 	  _M_next->_M_prior = _M_prior;
245ffeaf689SAlexander Kabaev 
246ffeaf689SAlexander Kabaev 	if (_M_sequence->_M_const_iterators == this)
247ffeaf689SAlexander Kabaev 	  _M_sequence->_M_const_iterators = _M_next;
248ffeaf689SAlexander Kabaev 	if (_M_sequence->_M_iterators == this)
249ffeaf689SAlexander Kabaev 	  _M_sequence->_M_iterators = _M_next;
250ffeaf689SAlexander Kabaev       }
251ffeaf689SAlexander Kabaev 
252ffeaf689SAlexander Kabaev     _M_sequence = 0;
253ffeaf689SAlexander Kabaev     _M_version = 0;
254ffeaf689SAlexander Kabaev     _M_prior = 0;
255ffeaf689SAlexander Kabaev     _M_next = 0;
256ffeaf689SAlexander Kabaev   }
257ffeaf689SAlexander Kabaev 
258ffeaf689SAlexander Kabaev   bool
259ffeaf689SAlexander Kabaev   _Safe_iterator_base::
_M_singular() const260ffeaf689SAlexander Kabaev   _M_singular() const
261ffeaf689SAlexander Kabaev   { return !_M_sequence || _M_version != _M_sequence->_M_version; }
262ffeaf689SAlexander Kabaev 
263ffeaf689SAlexander Kabaev   bool
264ffeaf689SAlexander Kabaev   _Safe_iterator_base::
_M_can_compare(const _Safe_iterator_base & __x) const265ffeaf689SAlexander Kabaev   _M_can_compare(const _Safe_iterator_base& __x) const
266ffeaf689SAlexander Kabaev   {
267*f8a1b7d9SAlexander Kabaev     return (!_M_singular()
268*f8a1b7d9SAlexander Kabaev 	    && !__x._M_singular() && _M_sequence == __x._M_sequence);
269ffeaf689SAlexander Kabaev   }
270ffeaf689SAlexander Kabaev 
271*f8a1b7d9SAlexander Kabaev   __gnu_cxx::__mutex&
272*f8a1b7d9SAlexander Kabaev   _Safe_iterator_base::
_M_get_mutex()273*f8a1b7d9SAlexander Kabaev   _M_get_mutex()
274*f8a1b7d9SAlexander Kabaev   { return safe_base_mutex; }
275*f8a1b7d9SAlexander Kabaev 
276ffeaf689SAlexander Kabaev   void
277ffeaf689SAlexander Kabaev   _Error_formatter::_Parameter::
_M_print_field(const _Error_formatter * __formatter,const char * __name) const278ffeaf689SAlexander Kabaev   _M_print_field(const _Error_formatter* __formatter, const char* __name) const
279ffeaf689SAlexander Kabaev   {
280ffeaf689SAlexander Kabaev     assert(this->_M_kind != _Parameter::__unused_param);
281ffeaf689SAlexander Kabaev     const int __bufsize = 64;
282ffeaf689SAlexander Kabaev     char __buf[__bufsize];
283ffeaf689SAlexander Kabaev 
284ffeaf689SAlexander Kabaev     if (_M_kind == __iterator)
285ffeaf689SAlexander Kabaev       {
286ffeaf689SAlexander Kabaev 	if (strcmp(__name, "name") == 0)
287ffeaf689SAlexander Kabaev 	  {
288ffeaf689SAlexander Kabaev 	    assert(_M_variant._M_iterator._M_name);
289ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(_M_variant._M_iterator._M_name);
290ffeaf689SAlexander Kabaev 	  }
291ffeaf689SAlexander Kabaev 	else if (strcmp(__name, "address") == 0)
292ffeaf689SAlexander Kabaev 	  {
293ffeaf689SAlexander Kabaev 	    __formatter->_M_format_word(__buf, __bufsize, "%p",
294ffeaf689SAlexander Kabaev 					_M_variant._M_iterator._M_address);
295ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(__buf);
296ffeaf689SAlexander Kabaev 	  }
297ffeaf689SAlexander Kabaev 	else if (strcmp(__name, "type") == 0)
298ffeaf689SAlexander Kabaev 	  {
299ffeaf689SAlexander Kabaev 	    assert(_M_variant._M_iterator._M_type);
300ffeaf689SAlexander Kabaev 	    // TBD: demangle!
301ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(_M_variant._M_iterator._M_type->name());
302ffeaf689SAlexander Kabaev 	  }
303ffeaf689SAlexander Kabaev 	else if (strcmp(__name, "constness") == 0)
304ffeaf689SAlexander Kabaev 	  {
305ffeaf689SAlexander Kabaev 	    static const char* __constness_names[__last_constness] =
306ffeaf689SAlexander Kabaev 	      {
307ffeaf689SAlexander Kabaev 		"<unknown>",
308ffeaf689SAlexander Kabaev 		"constant",
309ffeaf689SAlexander Kabaev 		"mutable"
310ffeaf689SAlexander Kabaev 	      };
311ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(__constness_names[_M_variant._M_iterator._M_constness]);
312ffeaf689SAlexander Kabaev 	  }
313ffeaf689SAlexander Kabaev 	else if (strcmp(__name, "state") == 0)
314ffeaf689SAlexander Kabaev 	  {
315ffeaf689SAlexander Kabaev 	    static const char* __state_names[__last_state] =
316ffeaf689SAlexander Kabaev 	      {
317ffeaf689SAlexander Kabaev 		"<unknown>",
318ffeaf689SAlexander Kabaev 		"singular",
319ffeaf689SAlexander Kabaev 		"dereferenceable (start-of-sequence)",
320ffeaf689SAlexander Kabaev 		"dereferenceable",
321ffeaf689SAlexander Kabaev 		"past-the-end"
322ffeaf689SAlexander Kabaev 	      };
323ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(__state_names[_M_variant._M_iterator._M_state]);
324ffeaf689SAlexander Kabaev 	  }
325ffeaf689SAlexander Kabaev 	else if (strcmp(__name, "sequence") == 0)
326ffeaf689SAlexander Kabaev 	  {
327ffeaf689SAlexander Kabaev 	    assert(_M_variant._M_iterator._M_sequence);
328ffeaf689SAlexander Kabaev 	    __formatter->_M_format_word(__buf, __bufsize, "%p",
329ffeaf689SAlexander Kabaev 					_M_variant._M_iterator._M_sequence);
330ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(__buf);
331ffeaf689SAlexander Kabaev 	  }
332ffeaf689SAlexander Kabaev 	else if (strcmp(__name, "seq_type") == 0)
333ffeaf689SAlexander Kabaev 	  {
334ffeaf689SAlexander Kabaev 	    // TBD: demangle!
335ffeaf689SAlexander Kabaev 	    assert(_M_variant._M_iterator._M_seq_type);
336ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(_M_variant._M_iterator._M_seq_type->name());
337ffeaf689SAlexander Kabaev 	  }
338ffeaf689SAlexander Kabaev 	else
339ffeaf689SAlexander Kabaev 	  assert(false);
340ffeaf689SAlexander Kabaev       }
341ffeaf689SAlexander Kabaev     else if (_M_kind == __sequence)
342ffeaf689SAlexander Kabaev       {
343ffeaf689SAlexander Kabaev 	if (strcmp(__name, "name") == 0)
344ffeaf689SAlexander Kabaev 	  {
345ffeaf689SAlexander Kabaev 	    assert(_M_variant._M_sequence._M_name);
346ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(_M_variant._M_sequence._M_name);
347ffeaf689SAlexander Kabaev 	  }
348ffeaf689SAlexander Kabaev 	else if (strcmp(__name, "address") == 0)
349ffeaf689SAlexander Kabaev 	  {
350ffeaf689SAlexander Kabaev 	    assert(_M_variant._M_sequence._M_address);
351ffeaf689SAlexander Kabaev 	    __formatter->_M_format_word(__buf, __bufsize, "%p",
352ffeaf689SAlexander Kabaev 					_M_variant._M_sequence._M_address);
353ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(__buf);
354ffeaf689SAlexander Kabaev 	  }
355ffeaf689SAlexander Kabaev 	else if (strcmp(__name, "type") == 0)
356ffeaf689SAlexander Kabaev 	  {
357ffeaf689SAlexander Kabaev 	    // TBD: demangle!
358ffeaf689SAlexander Kabaev 	    assert(_M_variant._M_sequence._M_type);
359ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(_M_variant._M_sequence._M_type->name());
360ffeaf689SAlexander Kabaev 	  }
361ffeaf689SAlexander Kabaev 	else
362ffeaf689SAlexander Kabaev 	  assert(false);
363ffeaf689SAlexander Kabaev       }
364ffeaf689SAlexander Kabaev     else if (_M_kind == __integer)
365ffeaf689SAlexander Kabaev       {
366ffeaf689SAlexander Kabaev 	if (strcmp(__name, "name") == 0)
367ffeaf689SAlexander Kabaev 	  {
368ffeaf689SAlexander Kabaev 	    assert(_M_variant._M_integer._M_name);
369ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(_M_variant._M_integer._M_name);
370ffeaf689SAlexander Kabaev 	  }
371ffeaf689SAlexander Kabaev 	else
372ffeaf689SAlexander Kabaev 	assert(false);
373ffeaf689SAlexander Kabaev       }
374ffeaf689SAlexander Kabaev     else if (_M_kind == __string)
375ffeaf689SAlexander Kabaev       {
376ffeaf689SAlexander Kabaev 	if (strcmp(__name, "name") == 0)
377ffeaf689SAlexander Kabaev 	  {
378ffeaf689SAlexander Kabaev 	    assert(_M_variant._M_string._M_name);
379ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(_M_variant._M_string._M_name);
380ffeaf689SAlexander Kabaev 	  }
381ffeaf689SAlexander Kabaev 	else
382ffeaf689SAlexander Kabaev 	  assert(false);
383ffeaf689SAlexander Kabaev       }
384ffeaf689SAlexander Kabaev     else
385ffeaf689SAlexander Kabaev       {
386ffeaf689SAlexander Kabaev 	assert(false);
387ffeaf689SAlexander Kabaev       }
388ffeaf689SAlexander Kabaev   }
389ffeaf689SAlexander Kabaev 
390ffeaf689SAlexander Kabaev   void
391ffeaf689SAlexander Kabaev   _Error_formatter::_Parameter::
_M_print_description(const _Error_formatter * __formatter) const392ffeaf689SAlexander Kabaev   _M_print_description(const _Error_formatter* __formatter) const
393ffeaf689SAlexander Kabaev   {
394ffeaf689SAlexander Kabaev     const int __bufsize = 128;
395ffeaf689SAlexander Kabaev     char __buf[__bufsize];
396ffeaf689SAlexander Kabaev 
397ffeaf689SAlexander Kabaev     if (_M_kind == __iterator)
398ffeaf689SAlexander Kabaev       {
399ffeaf689SAlexander Kabaev 	__formatter->_M_print_word("iterator ");
400ffeaf689SAlexander Kabaev 	if (_M_variant._M_iterator._M_name)
401ffeaf689SAlexander Kabaev 	  {
402ffeaf689SAlexander Kabaev 	    __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
403ffeaf689SAlexander Kabaev 					_M_variant._M_iterator._M_name);
404ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(__buf);
405ffeaf689SAlexander Kabaev 	  }
406ffeaf689SAlexander Kabaev 
407ffeaf689SAlexander Kabaev 	__formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
408ffeaf689SAlexander Kabaev 				    _M_variant._M_iterator._M_address);
409ffeaf689SAlexander Kabaev 	__formatter->_M_print_word(__buf);
410ffeaf689SAlexander Kabaev 	if (_M_variant._M_iterator._M_type)
411ffeaf689SAlexander Kabaev 	  {
412ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word("type = ");
413ffeaf689SAlexander Kabaev 	    _M_print_field(__formatter, "type");
414ffeaf689SAlexander Kabaev 
415ffeaf689SAlexander Kabaev 	    if (_M_variant._M_iterator._M_constness != __unknown_constness)
416ffeaf689SAlexander Kabaev 	      {
417ffeaf689SAlexander Kabaev 		__formatter->_M_print_word(" (");
418ffeaf689SAlexander Kabaev 		_M_print_field(__formatter, "constness");
419ffeaf689SAlexander Kabaev 		__formatter->_M_print_word(" iterator)");
420ffeaf689SAlexander Kabaev 	      }
421ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(";\n");
422ffeaf689SAlexander Kabaev 	  }
423ffeaf689SAlexander Kabaev 
424ffeaf689SAlexander Kabaev 	if (_M_variant._M_iterator._M_state != __unknown_state)
425ffeaf689SAlexander Kabaev 	  {
426ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word("  state = ");
427ffeaf689SAlexander Kabaev 	    _M_print_field(__formatter, "state");
428ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(";\n");
429ffeaf689SAlexander Kabaev 	  }
430ffeaf689SAlexander Kabaev 
431ffeaf689SAlexander Kabaev 	if (_M_variant._M_iterator._M_sequence)
432ffeaf689SAlexander Kabaev 	  {
433ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word("  references sequence ");
434ffeaf689SAlexander Kabaev 	    if (_M_variant._M_iterator._M_seq_type)
435ffeaf689SAlexander Kabaev 	      {
436ffeaf689SAlexander Kabaev 		__formatter->_M_print_word("with type `");
437ffeaf689SAlexander Kabaev 		_M_print_field(__formatter, "seq_type");
438ffeaf689SAlexander Kabaev 		__formatter->_M_print_word("' ");
439ffeaf689SAlexander Kabaev 	      }
440ffeaf689SAlexander Kabaev 
441ffeaf689SAlexander Kabaev 	    __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n",
442ffeaf689SAlexander Kabaev 					_M_variant._M_sequence._M_address);
443ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(__buf);
444ffeaf689SAlexander Kabaev 	  }
445ffeaf689SAlexander Kabaev 	__formatter->_M_print_word("}\n");
446ffeaf689SAlexander Kabaev       }
447ffeaf689SAlexander Kabaev     else if (_M_kind == __sequence)
448ffeaf689SAlexander Kabaev       {
449ffeaf689SAlexander Kabaev 	__formatter->_M_print_word("sequence ");
450ffeaf689SAlexander Kabaev 	if (_M_variant._M_sequence._M_name)
451ffeaf689SAlexander Kabaev 	  {
452ffeaf689SAlexander Kabaev 	    __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
453ffeaf689SAlexander Kabaev 					_M_variant._M_sequence._M_name);
454ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(__buf);
455ffeaf689SAlexander Kabaev 	  }
456ffeaf689SAlexander Kabaev 
457ffeaf689SAlexander Kabaev 	__formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
458ffeaf689SAlexander Kabaev 				    _M_variant._M_sequence._M_address);
459ffeaf689SAlexander Kabaev 	__formatter->_M_print_word(__buf);
460ffeaf689SAlexander Kabaev 
461ffeaf689SAlexander Kabaev 	if (_M_variant._M_sequence._M_type)
462ffeaf689SAlexander Kabaev 	  {
463ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word("  type = ");
464ffeaf689SAlexander Kabaev 	    _M_print_field(__formatter, "type");
465ffeaf689SAlexander Kabaev 	    __formatter->_M_print_word(";\n");
466ffeaf689SAlexander Kabaev 	  }
467ffeaf689SAlexander Kabaev 	__formatter->_M_print_word("}\n");
468ffeaf689SAlexander Kabaev       }
469ffeaf689SAlexander Kabaev   }
470ffeaf689SAlexander Kabaev 
471ffeaf689SAlexander Kabaev   const _Error_formatter&
_M_message(_Debug_msg_id __id) const472ffeaf689SAlexander Kabaev   _Error_formatter::_M_message(_Debug_msg_id __id) const
473ffeaf689SAlexander Kabaev   { return this->_M_message(_S_debug_messages[__id]); }
474ffeaf689SAlexander Kabaev 
475ffeaf689SAlexander Kabaev   void
_M_error() const476ffeaf689SAlexander Kabaev   _Error_formatter::_M_error() const
477ffeaf689SAlexander Kabaev   {
478ffeaf689SAlexander Kabaev     const int __bufsize = 128;
479ffeaf689SAlexander Kabaev     char __buf[__bufsize];
480ffeaf689SAlexander Kabaev 
481ffeaf689SAlexander Kabaev     // Emit file & line number information
482ffeaf689SAlexander Kabaev     _M_column = 1;
483ffeaf689SAlexander Kabaev     _M_wordwrap = false;
484ffeaf689SAlexander Kabaev     if (_M_file)
485ffeaf689SAlexander Kabaev       {
486ffeaf689SAlexander Kabaev 	_M_format_word(__buf, __bufsize, "%s:", _M_file);
487ffeaf689SAlexander Kabaev 	_M_print_word(__buf);
488ffeaf689SAlexander Kabaev 	_M_column += strlen(__buf);
489ffeaf689SAlexander Kabaev       }
490ffeaf689SAlexander Kabaev 
491ffeaf689SAlexander Kabaev     if (_M_line > 0)
492ffeaf689SAlexander Kabaev       {
493ffeaf689SAlexander Kabaev 	_M_format_word(__buf, __bufsize, "%u:", _M_line);
494ffeaf689SAlexander Kabaev 	_M_print_word(__buf);
495ffeaf689SAlexander Kabaev 	_M_column += strlen(__buf);
496ffeaf689SAlexander Kabaev       }
497ffeaf689SAlexander Kabaev 
498ffeaf689SAlexander Kabaev     _M_wordwrap = true;
499ffeaf689SAlexander Kabaev     _M_print_word("error: ");
500ffeaf689SAlexander Kabaev 
501ffeaf689SAlexander Kabaev     // Print the error message
502ffeaf689SAlexander Kabaev     assert(_M_text);
503ffeaf689SAlexander Kabaev     _M_print_string(_M_text);
504ffeaf689SAlexander Kabaev     _M_print_word(".\n");
505ffeaf689SAlexander Kabaev 
506ffeaf689SAlexander Kabaev     // Emit descriptions of the objects involved in the operation
507ffeaf689SAlexander Kabaev     _M_wordwrap = false;
508ffeaf689SAlexander Kabaev     bool __has_noninteger_parameters = false;
509ffeaf689SAlexander Kabaev     for (unsigned int __i = 0; __i < _M_num_parameters; ++__i)
510ffeaf689SAlexander Kabaev       {
511ffeaf689SAlexander Kabaev 	if (_M_parameters[__i]._M_kind == _Parameter::__iterator
512ffeaf689SAlexander Kabaev 	    || _M_parameters[__i]._M_kind == _Parameter::__sequence)
513ffeaf689SAlexander Kabaev 	  {
514ffeaf689SAlexander Kabaev 	    if (!__has_noninteger_parameters)
515ffeaf689SAlexander Kabaev 	      {
516ffeaf689SAlexander Kabaev 		_M_first_line = true;
517ffeaf689SAlexander Kabaev 		_M_print_word("\nObjects involved in the operation:\n");
518ffeaf689SAlexander Kabaev 		__has_noninteger_parameters = true;
519ffeaf689SAlexander Kabaev 	      }
520ffeaf689SAlexander Kabaev 	    _M_parameters[__i]._M_print_description(this);
521ffeaf689SAlexander Kabaev 	  }
522ffeaf689SAlexander Kabaev       }
523ffeaf689SAlexander Kabaev 
524ffeaf689SAlexander Kabaev     abort();
525ffeaf689SAlexander Kabaev   }
526ffeaf689SAlexander Kabaev 
527ffeaf689SAlexander Kabaev   template<typename _Tp>
528ffeaf689SAlexander Kabaev     void
_M_format_word(char * __buf,int __n,const char * __fmt,_Tp __s) const529ffeaf689SAlexander Kabaev     _Error_formatter::_M_format_word(char* __buf,
530ffeaf689SAlexander Kabaev 				     int __n __attribute__ ((__unused__)),
531ffeaf689SAlexander Kabaev 				     const char* __fmt, _Tp __s) const
532ffeaf689SAlexander Kabaev     {
533ffeaf689SAlexander Kabaev #ifdef _GLIBCXX_USE_C99
534ffeaf689SAlexander Kabaev       std::snprintf(__buf, __n, __fmt, __s);
535ffeaf689SAlexander Kabaev #else
536ffeaf689SAlexander Kabaev       std::sprintf(__buf, __fmt, __s);
537ffeaf689SAlexander Kabaev #endif
538ffeaf689SAlexander Kabaev     }
539ffeaf689SAlexander Kabaev 
540ffeaf689SAlexander Kabaev 
541ffeaf689SAlexander Kabaev   void
_M_print_word(const char * __word) const542ffeaf689SAlexander Kabaev   _Error_formatter::_M_print_word(const char* __word) const
543ffeaf689SAlexander Kabaev   {
544ffeaf689SAlexander Kabaev     if (!_M_wordwrap)
545ffeaf689SAlexander Kabaev       {
546ffeaf689SAlexander Kabaev 	fprintf(stderr, "%s", __word);
547ffeaf689SAlexander Kabaev 	return;
548ffeaf689SAlexander Kabaev       }
549ffeaf689SAlexander Kabaev 
550ffeaf689SAlexander Kabaev     size_t __length = strlen(__word);
551ffeaf689SAlexander Kabaev     if (__length == 0)
552ffeaf689SAlexander Kabaev       return;
553ffeaf689SAlexander Kabaev 
554ffeaf689SAlexander Kabaev     if ((_M_column + __length < _M_max_length)
555ffeaf689SAlexander Kabaev 	|| (__length >= _M_max_length && _M_column == 1))
556ffeaf689SAlexander Kabaev       {
557ffeaf689SAlexander Kabaev 	// If this isn't the first line, indent
558ffeaf689SAlexander Kabaev 	if (_M_column == 1 && !_M_first_line)
559ffeaf689SAlexander Kabaev 	  {
560ffeaf689SAlexander Kabaev 	    char __spacing[_M_indent + 1];
561ffeaf689SAlexander Kabaev 	    for (int i = 0; i < _M_indent; ++i)
562ffeaf689SAlexander Kabaev 	      __spacing[i] = ' ';
563ffeaf689SAlexander Kabaev 	    __spacing[_M_indent] = '\0';
564ffeaf689SAlexander Kabaev 	    fprintf(stderr, "%s", __spacing);
565ffeaf689SAlexander Kabaev 	    _M_column += _M_indent;
566ffeaf689SAlexander Kabaev 	  }
567ffeaf689SAlexander Kabaev 
568ffeaf689SAlexander Kabaev 	fprintf(stderr, "%s", __word);
569ffeaf689SAlexander Kabaev 	_M_column += __length;
570ffeaf689SAlexander Kabaev 
571ffeaf689SAlexander Kabaev 	if (__word[__length - 1] == '\n')
572ffeaf689SAlexander Kabaev 	  {
573ffeaf689SAlexander Kabaev 	    _M_first_line = false;
574ffeaf689SAlexander Kabaev 	    _M_column = 1;
575ffeaf689SAlexander Kabaev 	  }
576ffeaf689SAlexander Kabaev       }
577ffeaf689SAlexander Kabaev     else
578ffeaf689SAlexander Kabaev       {
579ffeaf689SAlexander Kabaev 	_M_column = 1;
580ffeaf689SAlexander Kabaev 	_M_print_word("\n");
581ffeaf689SAlexander Kabaev 	_M_print_word(__word);
582ffeaf689SAlexander Kabaev       }
583ffeaf689SAlexander Kabaev   }
584ffeaf689SAlexander Kabaev 
585ffeaf689SAlexander Kabaev   void
586ffeaf689SAlexander Kabaev   _Error_formatter::
_M_print_string(const char * __string) const587ffeaf689SAlexander Kabaev   _M_print_string(const char* __string) const
588ffeaf689SAlexander Kabaev   {
589ffeaf689SAlexander Kabaev     const char* __start = __string;
590*f8a1b7d9SAlexander Kabaev     const char* __finish = __start;
591ffeaf689SAlexander Kabaev     const int __bufsize = 128;
592ffeaf689SAlexander Kabaev     char __buf[__bufsize];
593ffeaf689SAlexander Kabaev 
594ffeaf689SAlexander Kabaev     while (*__start)
595ffeaf689SAlexander Kabaev       {
596ffeaf689SAlexander Kabaev 	if (*__start != '%')
597ffeaf689SAlexander Kabaev 	  {
598*f8a1b7d9SAlexander Kabaev 	    // [__start, __finish) denotes the next word
599*f8a1b7d9SAlexander Kabaev 	    __finish = __start;
600*f8a1b7d9SAlexander Kabaev 	    while (isalnum(*__finish))
601*f8a1b7d9SAlexander Kabaev 	      ++__finish;
602*f8a1b7d9SAlexander Kabaev 	    if (__start == __finish)
603*f8a1b7d9SAlexander Kabaev 	      ++__finish;
604*f8a1b7d9SAlexander Kabaev 	    if (isspace(*__finish))
605*f8a1b7d9SAlexander Kabaev 	      ++__finish;
606ffeaf689SAlexander Kabaev 
607*f8a1b7d9SAlexander Kabaev 	    const ptrdiff_t __len = __finish - __start;
608f260e61bSAlexander Kabaev 	    assert(__len < __bufsize);
609f260e61bSAlexander Kabaev 	    memcpy(__buf, __start, __len);
610f260e61bSAlexander Kabaev 	    __buf[__len] = '\0';
611ffeaf689SAlexander Kabaev 	    _M_print_word(__buf);
612*f8a1b7d9SAlexander Kabaev 	    __start = __finish;
613ffeaf689SAlexander Kabaev 
614ffeaf689SAlexander Kabaev 	    // Skip extra whitespace
615ffeaf689SAlexander Kabaev 	    while (*__start == ' ')
616ffeaf689SAlexander Kabaev 	      ++__start;
617ffeaf689SAlexander Kabaev 
618ffeaf689SAlexander Kabaev 	    continue;
619ffeaf689SAlexander Kabaev 	  }
620ffeaf689SAlexander Kabaev 
621ffeaf689SAlexander Kabaev 	++__start;
622ffeaf689SAlexander Kabaev 	assert(*__start);
623ffeaf689SAlexander Kabaev 	if (*__start == '%')
624ffeaf689SAlexander Kabaev 	  {
625ffeaf689SAlexander Kabaev 	    _M_print_word("%");
626ffeaf689SAlexander Kabaev 	    ++__start;
627ffeaf689SAlexander Kabaev 	    continue;
628ffeaf689SAlexander Kabaev 	  }
629ffeaf689SAlexander Kabaev 
630ffeaf689SAlexander Kabaev 	// Get the parameter number
631ffeaf689SAlexander Kabaev 	assert(*__start >= '1' && *__start <= '9');
632ffeaf689SAlexander Kabaev 	size_t __param = *__start - '0';
633ffeaf689SAlexander Kabaev 	--__param;
634ffeaf689SAlexander Kabaev 	assert(__param < _M_num_parameters);
635ffeaf689SAlexander Kabaev 
636ffeaf689SAlexander Kabaev 	// '.' separates the parameter number from the field
637ffeaf689SAlexander Kabaev 	// name, if there is one.
638ffeaf689SAlexander Kabaev 	++__start;
639ffeaf689SAlexander Kabaev 	if (*__start != '.')
640ffeaf689SAlexander Kabaev 	  {
641ffeaf689SAlexander Kabaev 	    assert(*__start == ';');
642ffeaf689SAlexander Kabaev 	    ++__start;
643ffeaf689SAlexander Kabaev 	    __buf[0] = '\0';
644ffeaf689SAlexander Kabaev 	    if (_M_parameters[__param]._M_kind == _Parameter::__integer)
645ffeaf689SAlexander Kabaev 	      {
646ffeaf689SAlexander Kabaev 		_M_format_word(__buf, __bufsize, "%ld",
647ffeaf689SAlexander Kabaev 			       _M_parameters[__param]._M_variant._M_integer._M_value);
648ffeaf689SAlexander Kabaev 		_M_print_word(__buf);
649ffeaf689SAlexander Kabaev 	      }
650ffeaf689SAlexander Kabaev 	    else if (_M_parameters[__param]._M_kind == _Parameter::__string)
651ffeaf689SAlexander Kabaev 	      _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value);
652ffeaf689SAlexander Kabaev 	    continue;
653ffeaf689SAlexander Kabaev 	  }
654ffeaf689SAlexander Kabaev 
655ffeaf689SAlexander Kabaev 	// Extract the field name we want
656ffeaf689SAlexander Kabaev 	enum { __max_field_len = 16 };
657ffeaf689SAlexander Kabaev 	char __field[__max_field_len];
658ffeaf689SAlexander Kabaev 	int __field_idx = 0;
659ffeaf689SAlexander Kabaev 	++__start;
660ffeaf689SAlexander Kabaev 	while (*__start != ';')
661ffeaf689SAlexander Kabaev 	  {
662ffeaf689SAlexander Kabaev 	    assert(*__start);
663ffeaf689SAlexander Kabaev 	    assert(__field_idx < __max_field_len-1);
664ffeaf689SAlexander Kabaev 	    __field[__field_idx++] = *__start++;
665ffeaf689SAlexander Kabaev 	  }
666ffeaf689SAlexander Kabaev 	++__start;
667ffeaf689SAlexander Kabaev 	__field[__field_idx] = 0;
668ffeaf689SAlexander Kabaev 
669ffeaf689SAlexander Kabaev 	_M_parameters[__param]._M_print_field(this, __field);
670ffeaf689SAlexander Kabaev       }
671ffeaf689SAlexander Kabaev   }
672ffeaf689SAlexander Kabaev 
673ffeaf689SAlexander Kabaev   // Instantiations.
674ffeaf689SAlexander Kabaev   template
675ffeaf689SAlexander Kabaev     void
676*f8a1b7d9SAlexander Kabaev     _Error_formatter::_M_format_word(char*, int, const char*,
677*f8a1b7d9SAlexander Kabaev 				     const void*) const;
678ffeaf689SAlexander Kabaev 
679ffeaf689SAlexander Kabaev   template
680ffeaf689SAlexander Kabaev     void
681*f8a1b7d9SAlexander Kabaev     _Error_formatter::_M_format_word(char*, int, const char*, long) const;
682ffeaf689SAlexander Kabaev 
683ffeaf689SAlexander Kabaev   template
684ffeaf689SAlexander Kabaev     void
685*f8a1b7d9SAlexander Kabaev     _Error_formatter::_M_format_word(char*, int, const char*,
686*f8a1b7d9SAlexander Kabaev 				     std::size_t) const;
687ffeaf689SAlexander Kabaev 
688ffeaf689SAlexander Kabaev   template
689ffeaf689SAlexander Kabaev     void
690*f8a1b7d9SAlexander Kabaev     _Error_formatter::_M_format_word(char*, int, const char*,
691*f8a1b7d9SAlexander Kabaev 				     const char*) const;
692ffeaf689SAlexander Kabaev } // namespace __gnu_debug
693