xref: /openbsd-src/gnu/gcc/libstdc++-v3/src/debug.cc (revision 9777fa2d069b579e3f40e4861fc9248ad693893d)
1404b540aSrobert // Debugging mode support code -*- C++ -*-
2404b540aSrobert 
3404b540aSrobert // Copyright (C) 2003, 2004, 2005, 2006
4404b540aSrobert // Free Software Foundation, Inc.
5404b540aSrobert //
6404b540aSrobert // This file is part of the GNU ISO C++ Library.  This library is free
7404b540aSrobert // software; you can redistribute it and/or modify it under the
8404b540aSrobert // terms of the GNU General Public License as published by the
9404b540aSrobert // Free Software Foundation; either version 2, or (at your option)
10404b540aSrobert // any later version.
11404b540aSrobert 
12404b540aSrobert // This library is distributed in the hope that it will be useful,
13404b540aSrobert // but WITHOUT ANY WARRANTY; without even the implied warranty of
14404b540aSrobert // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15404b540aSrobert // GNU General Public License for more details.
16404b540aSrobert 
17404b540aSrobert // You should have received a copy of the GNU General Public License along
18404b540aSrobert // with this library; see the file COPYING.  If not, write to the Free
19404b540aSrobert // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20404b540aSrobert // USA.
21404b540aSrobert 
22404b540aSrobert // As a special exception, you may use this file as part of a free software
23404b540aSrobert // library without restriction.  Specifically, if other files instantiate
24404b540aSrobert // templates or use macros or inline functions from this file, or you compile
25404b540aSrobert // this file and link it with other files to produce an executable, this
26404b540aSrobert // file does not by itself cause the resulting executable to be covered by
27404b540aSrobert // the GNU General Public License.  This exception does not however
28404b540aSrobert // invalidate any other reasons why the executable file might be covered by
29404b540aSrobert // the GNU General Public License.
30404b540aSrobert 
31404b540aSrobert #include <debug/debug.h>
32404b540aSrobert #include <debug/safe_sequence.h>
33404b540aSrobert #include <debug/safe_iterator.h>
34404b540aSrobert #include <algorithm>
35404b540aSrobert #include <cassert>
36404b540aSrobert #include <cstring>
37404b540aSrobert #include <cctype>
38404b540aSrobert 
39404b540aSrobert using namespace std;
40404b540aSrobert 
41404b540aSrobert namespace
42404b540aSrobert {
43404b540aSrobert   __gnu_cxx::__mutex safe_base_mutex;
44404b540aSrobert } // anonymous namespace
45404b540aSrobert 
46404b540aSrobert namespace __gnu_debug
47404b540aSrobert {
48*9777fa2dSzhuk   static const char* _S_debug_messages[] =
49404b540aSrobert   {
50404b540aSrobert     "function requires a valid iterator range [%1.name;, %2.name;)",
51404b540aSrobert     "attempt to insert into container with a singular iterator",
52404b540aSrobert     "attempt to insert into container with an iterator"
53404b540aSrobert     " from a different container",
54404b540aSrobert     "attempt to erase from container with a %2.state; iterator",
55404b540aSrobert     "attempt to erase from container with an iterator"
56404b540aSrobert     " from a different container",
57404b540aSrobert     "attempt to subscript container with out-of-bounds index %2;,"
58404b540aSrobert     " but container only holds %3; elements",
59404b540aSrobert     "attempt to access an element in an empty container",
60404b540aSrobert     "elements in iterator range [%1.name;, %2.name;)"
61404b540aSrobert     " are not partitioned by the value %3;",
62404b540aSrobert     "elements in iterator range [%1.name;, %2.name;)"
63404b540aSrobert     " are not partitioned by the predicate %3; and value %4;",
64404b540aSrobert     "elements in iterator range [%1.name;, %2.name;) are not sorted",
65404b540aSrobert     "elements in iterator range [%1.name;, %2.name;)"
66404b540aSrobert     " are not sorted according to the predicate %3;",
67404b540aSrobert     "elements in iterator range [%1.name;, %2.name;) do not form a heap",
68404b540aSrobert     "elements in iterator range [%1.name;, %2.name;)"
69404b540aSrobert     " do not form a heap with respect to the predicate %3;",
70404b540aSrobert     "attempt to write through a singular bitset reference",
71404b540aSrobert     "attempt to read from a singular bitset reference",
72404b540aSrobert     "attempt to flip a singular bitset reference",
73404b540aSrobert     "attempt to splice a list into itself",
74404b540aSrobert     "attempt to splice lists with inequal allocators",
75404b540aSrobert     "attempt to splice elements referenced by a %1.state; iterator",
76404b540aSrobert     "attempt to splice an iterator from a different container",
77404b540aSrobert     "splice destination %1.name;"
78404b540aSrobert     " occurs within source range [%2.name;, %3.name;)",
79404b540aSrobert     "attempt to initialize an iterator that will immediately become singular",
80404b540aSrobert     "attempt to copy-construct an iterator from a singular iterator",
81404b540aSrobert     "attempt to construct a constant iterator"
82404b540aSrobert     " from a singular mutable iterator",
83404b540aSrobert     "attempt to copy from a singular iterator",
84404b540aSrobert     "attempt to dereference a %1.state; iterator",
85404b540aSrobert     "attempt to increment a %1.state; iterator",
86404b540aSrobert     "attempt to decrement a %1.state; iterator",
87404b540aSrobert     "attempt to subscript a %1.state; iterator %2; step from"
88404b540aSrobert     " its current position, which falls outside its dereferenceable range",
89404b540aSrobert     "attempt to advance a %1.state; iterator %2; steps,"
90404b540aSrobert     " which falls outside its valid range",
91404b540aSrobert     "attempt to retreat a %1.state; iterator %2; steps,"
92404b540aSrobert     " which falls outside its valid range",
93404b540aSrobert     "attempt to compare a %1.state; iterator to a %2.state; iterator",
94404b540aSrobert     "attempt to compare iterators from different sequences",
95404b540aSrobert     "attempt to order a %1.state; iterator to a %2.state; iterator",
96404b540aSrobert     "attempt to order iterators from different sequences",
97404b540aSrobert     "attempt to compute the difference between a %1.state;"
98404b540aSrobert     " iterator to a %2.state; iterator",
99404b540aSrobert     "attempt to compute the different between two iterators"
100404b540aSrobert     " from different sequences",
101404b540aSrobert     "attempt to dereference an end-of-stream istream_iterator",
102404b540aSrobert     "attempt to increment an end-of-stream istream_iterator",
103404b540aSrobert     "attempt to output via an ostream_iterator with no associated stream",
104404b540aSrobert     "attempt to dereference an end-of-stream istreambuf_iterator"
105404b540aSrobert     " (this is a GNU extension)",
106404b540aSrobert     "attempt to increment an end-of-stream istreambuf_iterator"
107404b540aSrobert   };
108404b540aSrobert 
109404b540aSrobert   void
110404b540aSrobert   _Safe_sequence_base::
_M_detach_all()111404b540aSrobert   _M_detach_all()
112404b540aSrobert   {
113404b540aSrobert     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
114404b540aSrobert     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
115404b540aSrobert       {
116404b540aSrobert 	_Safe_iterator_base* __old = __iter;
117404b540aSrobert 	__iter = __iter->_M_next;
118404b540aSrobert 	__old->_M_detach_single();
119404b540aSrobert       }
120404b540aSrobert 
121404b540aSrobert     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
122404b540aSrobert       {
123404b540aSrobert 	_Safe_iterator_base* __old = __iter2;
124404b540aSrobert 	__iter2 = __iter2->_M_next;
125404b540aSrobert 	__old->_M_detach_single();
126404b540aSrobert       }
127404b540aSrobert   }
128404b540aSrobert 
129404b540aSrobert   void
130404b540aSrobert   _Safe_sequence_base::
_M_detach_singular()131404b540aSrobert   _M_detach_singular()
132404b540aSrobert   {
133404b540aSrobert     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
134404b540aSrobert     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
135404b540aSrobert       {
136404b540aSrobert 	_Safe_iterator_base* __old = __iter;
137404b540aSrobert 	__iter = __iter->_M_next;
138404b540aSrobert 	if (__old->_M_singular())
139404b540aSrobert 	  __old->_M_detach_single();
140404b540aSrobert       }
141404b540aSrobert 
142404b540aSrobert     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
143404b540aSrobert       {
144404b540aSrobert 	_Safe_iterator_base* __old = __iter2;
145404b540aSrobert 	__iter2 = __iter2->_M_next;
146404b540aSrobert 	if (__old->_M_singular())
147404b540aSrobert 	  __old->_M_detach_single();
148404b540aSrobert       }
149404b540aSrobert   }
150404b540aSrobert 
151404b540aSrobert   void
152404b540aSrobert   _Safe_sequence_base::
_M_revalidate_singular()153404b540aSrobert   _M_revalidate_singular()
154404b540aSrobert   {
155404b540aSrobert     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
156404b540aSrobert     for (_Safe_iterator_base* __iter = _M_iterators; __iter;
157404b540aSrobert 	 __iter = __iter->_M_next)
158404b540aSrobert       __iter->_M_version = _M_version;
159404b540aSrobert 
160404b540aSrobert     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
161404b540aSrobert 	 __iter2 = __iter2->_M_next)
162404b540aSrobert       __iter2->_M_version = _M_version;
163404b540aSrobert   }
164404b540aSrobert 
165404b540aSrobert   void
166404b540aSrobert   _Safe_sequence_base::
_M_swap(_Safe_sequence_base & __x)167404b540aSrobert   _M_swap(_Safe_sequence_base& __x)
168404b540aSrobert   {
169404b540aSrobert     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
170404b540aSrobert     swap(_M_iterators, __x._M_iterators);
171404b540aSrobert     swap(_M_const_iterators, __x._M_const_iterators);
172404b540aSrobert     swap(_M_version, __x._M_version);
173404b540aSrobert     _Safe_iterator_base* __iter;
174404b540aSrobert     for (__iter = _M_iterators; __iter; __iter = __iter->_M_next)
175404b540aSrobert       __iter->_M_sequence = this;
176404b540aSrobert     for (__iter = __x._M_iterators; __iter; __iter = __iter->_M_next)
177404b540aSrobert       __iter->_M_sequence = &__x;
178404b540aSrobert     for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next)
179404b540aSrobert       __iter->_M_sequence = this;
180404b540aSrobert     for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next)
181404b540aSrobert       __iter->_M_sequence = &__x;
182404b540aSrobert   }
183404b540aSrobert 
184404b540aSrobert   __gnu_cxx::__mutex&
185404b540aSrobert   _Safe_sequence_base::
_M_get_mutex()186404b540aSrobert   _M_get_mutex()
187404b540aSrobert   { return safe_base_mutex; }
188404b540aSrobert 
189404b540aSrobert   void
190404b540aSrobert   _Safe_iterator_base::
_M_attach(_Safe_sequence_base * __seq,bool __constant)191404b540aSrobert   _M_attach(_Safe_sequence_base* __seq, bool __constant)
192404b540aSrobert   {
193404b540aSrobert     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
194404b540aSrobert     _M_attach_single(__seq, __constant);
195404b540aSrobert   }
196404b540aSrobert 
197404b540aSrobert   void
198404b540aSrobert   _Safe_iterator_base::
_M_attach_single(_Safe_sequence_base * __seq,bool __constant)199404b540aSrobert   _M_attach_single(_Safe_sequence_base* __seq, bool __constant)
200404b540aSrobert   {
201404b540aSrobert     _M_detach_single();
202404b540aSrobert 
203404b540aSrobert     // Attach to the new sequence (if there is one)
204404b540aSrobert     if (__seq)
205404b540aSrobert       {
206404b540aSrobert 	_M_sequence = __seq;
207404b540aSrobert 	_M_version = _M_sequence->_M_version;
208404b540aSrobert 	_M_prior = 0;
209404b540aSrobert 	if (__constant)
210404b540aSrobert 	  {
211404b540aSrobert 	    _M_next = _M_sequence->_M_const_iterators;
212404b540aSrobert 	    if (_M_next)
213404b540aSrobert 	      _M_next->_M_prior = this;
214404b540aSrobert 	    _M_sequence->_M_const_iterators = this;
215404b540aSrobert 	  }
216404b540aSrobert 	else
217404b540aSrobert 	  {
218404b540aSrobert 	    _M_next = _M_sequence->_M_iterators;
219404b540aSrobert 	    if (_M_next)
220404b540aSrobert 	      _M_next->_M_prior = this;
221404b540aSrobert 	    _M_sequence->_M_iterators = this;
222404b540aSrobert 	  }
223404b540aSrobert       }
224404b540aSrobert   }
225404b540aSrobert 
226404b540aSrobert   void
227404b540aSrobert   _Safe_iterator_base::
_M_detach()228404b540aSrobert   _M_detach()
229404b540aSrobert   {
230404b540aSrobert     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
231404b540aSrobert     _M_detach_single();
232404b540aSrobert   }
233404b540aSrobert 
234404b540aSrobert   void
235404b540aSrobert   _Safe_iterator_base::
_M_detach_single()236404b540aSrobert   _M_detach_single()
237404b540aSrobert   {
238404b540aSrobert     if (_M_sequence)
239404b540aSrobert       {
240404b540aSrobert 	// Remove us from this sequence's list
241404b540aSrobert 	if (_M_prior)
242404b540aSrobert 	  _M_prior->_M_next = _M_next;
243404b540aSrobert 	if (_M_next)
244404b540aSrobert 	  _M_next->_M_prior = _M_prior;
245404b540aSrobert 
246404b540aSrobert 	if (_M_sequence->_M_const_iterators == this)
247404b540aSrobert 	  _M_sequence->_M_const_iterators = _M_next;
248404b540aSrobert 	if (_M_sequence->_M_iterators == this)
249404b540aSrobert 	  _M_sequence->_M_iterators = _M_next;
250404b540aSrobert       }
251404b540aSrobert 
252404b540aSrobert     _M_sequence = 0;
253404b540aSrobert     _M_version = 0;
254404b540aSrobert     _M_prior = 0;
255404b540aSrobert     _M_next = 0;
256404b540aSrobert   }
257404b540aSrobert 
258404b540aSrobert   bool
259404b540aSrobert   _Safe_iterator_base::
_M_singular() const260404b540aSrobert   _M_singular() const
261404b540aSrobert   { return !_M_sequence || _M_version != _M_sequence->_M_version; }
262404b540aSrobert 
263404b540aSrobert   bool
264404b540aSrobert   _Safe_iterator_base::
_M_can_compare(const _Safe_iterator_base & __x) const265404b540aSrobert   _M_can_compare(const _Safe_iterator_base& __x) const
266404b540aSrobert   {
267404b540aSrobert     return (!_M_singular()
268404b540aSrobert 	    && !__x._M_singular() && _M_sequence == __x._M_sequence);
269404b540aSrobert   }
270404b540aSrobert 
271404b540aSrobert   __gnu_cxx::__mutex&
272404b540aSrobert   _Safe_iterator_base::
_M_get_mutex()273404b540aSrobert   _M_get_mutex()
274404b540aSrobert   { return safe_base_mutex; }
275404b540aSrobert 
276404b540aSrobert   void
277404b540aSrobert   _Error_formatter::_Parameter::
_M_print_field(const _Error_formatter * __formatter,const char * __name) const278404b540aSrobert   _M_print_field(const _Error_formatter* __formatter, const char* __name) const
279404b540aSrobert   {
280404b540aSrobert     assert(this->_M_kind != _Parameter::__unused_param);
281404b540aSrobert     const int __bufsize = 64;
282404b540aSrobert     char __buf[__bufsize];
283404b540aSrobert 
284404b540aSrobert     if (_M_kind == __iterator)
285404b540aSrobert       {
286404b540aSrobert 	if (strcmp(__name, "name") == 0)
287404b540aSrobert 	  {
288404b540aSrobert 	    assert(_M_variant._M_iterator._M_name);
289404b540aSrobert 	    __formatter->_M_print_word(_M_variant._M_iterator._M_name);
290404b540aSrobert 	  }
291404b540aSrobert 	else if (strcmp(__name, "address") == 0)
292404b540aSrobert 	  {
293404b540aSrobert 	    __formatter->_M_format_word(__buf, __bufsize, "%p",
294404b540aSrobert 					_M_variant._M_iterator._M_address);
295404b540aSrobert 	    __formatter->_M_print_word(__buf);
296404b540aSrobert 	  }
297404b540aSrobert 	else if (strcmp(__name, "type") == 0)
298404b540aSrobert 	  {
299404b540aSrobert 	    assert(_M_variant._M_iterator._M_type);
300404b540aSrobert 	    // TBD: demangle!
301404b540aSrobert 	    __formatter->_M_print_word(_M_variant._M_iterator._M_type->name());
302404b540aSrobert 	  }
303404b540aSrobert 	else if (strcmp(__name, "constness") == 0)
304404b540aSrobert 	  {
305404b540aSrobert 	    static const char* __constness_names[__last_constness] =
306404b540aSrobert 	      {
307404b540aSrobert 		"<unknown>",
308404b540aSrobert 		"constant",
309404b540aSrobert 		"mutable"
310404b540aSrobert 	      };
311404b540aSrobert 	    __formatter->_M_print_word(__constness_names[_M_variant._M_iterator._M_constness]);
312404b540aSrobert 	  }
313404b540aSrobert 	else if (strcmp(__name, "state") == 0)
314404b540aSrobert 	  {
315404b540aSrobert 	    static const char* __state_names[__last_state] =
316404b540aSrobert 	      {
317404b540aSrobert 		"<unknown>",
318404b540aSrobert 		"singular",
319404b540aSrobert 		"dereferenceable (start-of-sequence)",
320404b540aSrobert 		"dereferenceable",
321404b540aSrobert 		"past-the-end"
322404b540aSrobert 	      };
323404b540aSrobert 	    __formatter->_M_print_word(__state_names[_M_variant._M_iterator._M_state]);
324404b540aSrobert 	  }
325404b540aSrobert 	else if (strcmp(__name, "sequence") == 0)
326404b540aSrobert 	  {
327404b540aSrobert 	    assert(_M_variant._M_iterator._M_sequence);
328404b540aSrobert 	    __formatter->_M_format_word(__buf, __bufsize, "%p",
329404b540aSrobert 					_M_variant._M_iterator._M_sequence);
330404b540aSrobert 	    __formatter->_M_print_word(__buf);
331404b540aSrobert 	  }
332404b540aSrobert 	else if (strcmp(__name, "seq_type") == 0)
333404b540aSrobert 	  {
334404b540aSrobert 	    // TBD: demangle!
335404b540aSrobert 	    assert(_M_variant._M_iterator._M_seq_type);
336404b540aSrobert 	    __formatter->_M_print_word(_M_variant._M_iterator._M_seq_type->name());
337404b540aSrobert 	  }
338404b540aSrobert 	else
339404b540aSrobert 	  assert(false);
340404b540aSrobert       }
341404b540aSrobert     else if (_M_kind == __sequence)
342404b540aSrobert       {
343404b540aSrobert 	if (strcmp(__name, "name") == 0)
344404b540aSrobert 	  {
345404b540aSrobert 	    assert(_M_variant._M_sequence._M_name);
346404b540aSrobert 	    __formatter->_M_print_word(_M_variant._M_sequence._M_name);
347404b540aSrobert 	  }
348404b540aSrobert 	else if (strcmp(__name, "address") == 0)
349404b540aSrobert 	  {
350404b540aSrobert 	    assert(_M_variant._M_sequence._M_address);
351404b540aSrobert 	    __formatter->_M_format_word(__buf, __bufsize, "%p",
352404b540aSrobert 					_M_variant._M_sequence._M_address);
353404b540aSrobert 	    __formatter->_M_print_word(__buf);
354404b540aSrobert 	  }
355404b540aSrobert 	else if (strcmp(__name, "type") == 0)
356404b540aSrobert 	  {
357404b540aSrobert 	    // TBD: demangle!
358404b540aSrobert 	    assert(_M_variant._M_sequence._M_type);
359404b540aSrobert 	    __formatter->_M_print_word(_M_variant._M_sequence._M_type->name());
360404b540aSrobert 	  }
361404b540aSrobert 	else
362404b540aSrobert 	  assert(false);
363404b540aSrobert       }
364404b540aSrobert     else if (_M_kind == __integer)
365404b540aSrobert       {
366404b540aSrobert 	if (strcmp(__name, "name") == 0)
367404b540aSrobert 	  {
368404b540aSrobert 	    assert(_M_variant._M_integer._M_name);
369404b540aSrobert 	    __formatter->_M_print_word(_M_variant._M_integer._M_name);
370404b540aSrobert 	  }
371404b540aSrobert 	else
372404b540aSrobert 	assert(false);
373404b540aSrobert       }
374404b540aSrobert     else if (_M_kind == __string)
375404b540aSrobert       {
376404b540aSrobert 	if (strcmp(__name, "name") == 0)
377404b540aSrobert 	  {
378404b540aSrobert 	    assert(_M_variant._M_string._M_name);
379404b540aSrobert 	    __formatter->_M_print_word(_M_variant._M_string._M_name);
380404b540aSrobert 	  }
381404b540aSrobert 	else
382404b540aSrobert 	  assert(false);
383404b540aSrobert       }
384404b540aSrobert     else
385404b540aSrobert       {
386404b540aSrobert 	assert(false);
387404b540aSrobert       }
388404b540aSrobert   }
389404b540aSrobert 
390404b540aSrobert   void
391404b540aSrobert   _Error_formatter::_Parameter::
_M_print_description(const _Error_formatter * __formatter) const392404b540aSrobert   _M_print_description(const _Error_formatter* __formatter) const
393404b540aSrobert   {
394404b540aSrobert     const int __bufsize = 128;
395404b540aSrobert     char __buf[__bufsize];
396404b540aSrobert 
397404b540aSrobert     if (_M_kind == __iterator)
398404b540aSrobert       {
399404b540aSrobert 	__formatter->_M_print_word("iterator ");
400404b540aSrobert 	if (_M_variant._M_iterator._M_name)
401404b540aSrobert 	  {
402404b540aSrobert 	    __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
403404b540aSrobert 					_M_variant._M_iterator._M_name);
404404b540aSrobert 	    __formatter->_M_print_word(__buf);
405404b540aSrobert 	  }
406404b540aSrobert 
407404b540aSrobert 	__formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
408404b540aSrobert 				    _M_variant._M_iterator._M_address);
409404b540aSrobert 	__formatter->_M_print_word(__buf);
410404b540aSrobert 	if (_M_variant._M_iterator._M_type)
411404b540aSrobert 	  {
412404b540aSrobert 	    __formatter->_M_print_word("type = ");
413404b540aSrobert 	    _M_print_field(__formatter, "type");
414404b540aSrobert 
415404b540aSrobert 	    if (_M_variant._M_iterator._M_constness != __unknown_constness)
416404b540aSrobert 	      {
417404b540aSrobert 		__formatter->_M_print_word(" (");
418404b540aSrobert 		_M_print_field(__formatter, "constness");
419404b540aSrobert 		__formatter->_M_print_word(" iterator)");
420404b540aSrobert 	      }
421404b540aSrobert 	    __formatter->_M_print_word(";\n");
422404b540aSrobert 	  }
423404b540aSrobert 
424404b540aSrobert 	if (_M_variant._M_iterator._M_state != __unknown_state)
425404b540aSrobert 	  {
426404b540aSrobert 	    __formatter->_M_print_word("  state = ");
427404b540aSrobert 	    _M_print_field(__formatter, "state");
428404b540aSrobert 	    __formatter->_M_print_word(";\n");
429404b540aSrobert 	  }
430404b540aSrobert 
431404b540aSrobert 	if (_M_variant._M_iterator._M_sequence)
432404b540aSrobert 	  {
433404b540aSrobert 	    __formatter->_M_print_word("  references sequence ");
434404b540aSrobert 	    if (_M_variant._M_iterator._M_seq_type)
435404b540aSrobert 	      {
436404b540aSrobert 		__formatter->_M_print_word("with type `");
437404b540aSrobert 		_M_print_field(__formatter, "seq_type");
438404b540aSrobert 		__formatter->_M_print_word("' ");
439404b540aSrobert 	      }
440404b540aSrobert 
441404b540aSrobert 	    __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n",
442404b540aSrobert 					_M_variant._M_sequence._M_address);
443404b540aSrobert 	    __formatter->_M_print_word(__buf);
444404b540aSrobert 	  }
445404b540aSrobert 	__formatter->_M_print_word("}\n");
446404b540aSrobert       }
447404b540aSrobert     else if (_M_kind == __sequence)
448404b540aSrobert       {
449404b540aSrobert 	__formatter->_M_print_word("sequence ");
450404b540aSrobert 	if (_M_variant._M_sequence._M_name)
451404b540aSrobert 	  {
452404b540aSrobert 	    __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
453404b540aSrobert 					_M_variant._M_sequence._M_name);
454404b540aSrobert 	    __formatter->_M_print_word(__buf);
455404b540aSrobert 	  }
456404b540aSrobert 
457404b540aSrobert 	__formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
458404b540aSrobert 				    _M_variant._M_sequence._M_address);
459404b540aSrobert 	__formatter->_M_print_word(__buf);
460404b540aSrobert 
461404b540aSrobert 	if (_M_variant._M_sequence._M_type)
462404b540aSrobert 	  {
463404b540aSrobert 	    __formatter->_M_print_word("  type = ");
464404b540aSrobert 	    _M_print_field(__formatter, "type");
465404b540aSrobert 	    __formatter->_M_print_word(";\n");
466404b540aSrobert 	  }
467404b540aSrobert 	__formatter->_M_print_word("}\n");
468404b540aSrobert       }
469404b540aSrobert   }
470404b540aSrobert 
471404b540aSrobert   const _Error_formatter&
_M_message(_Debug_msg_id __id) const472404b540aSrobert   _Error_formatter::_M_message(_Debug_msg_id __id) const
473404b540aSrobert   { return this->_M_message(_S_debug_messages[__id]); }
474404b540aSrobert 
475404b540aSrobert   void
_M_error() const476404b540aSrobert   _Error_formatter::_M_error() const
477404b540aSrobert   {
478404b540aSrobert     const int __bufsize = 128;
479404b540aSrobert     char __buf[__bufsize];
480404b540aSrobert 
481404b540aSrobert     // Emit file & line number information
482404b540aSrobert     _M_column = 1;
483404b540aSrobert     _M_wordwrap = false;
484404b540aSrobert     if (_M_file)
485404b540aSrobert       {
486404b540aSrobert 	_M_format_word(__buf, __bufsize, "%s:", _M_file);
487404b540aSrobert 	_M_print_word(__buf);
488404b540aSrobert 	_M_column += strlen(__buf);
489404b540aSrobert       }
490404b540aSrobert 
491404b540aSrobert     if (_M_line > 0)
492404b540aSrobert       {
493404b540aSrobert 	_M_format_word(__buf, __bufsize, "%u:", _M_line);
494404b540aSrobert 	_M_print_word(__buf);
495404b540aSrobert 	_M_column += strlen(__buf);
496404b540aSrobert       }
497404b540aSrobert 
498404b540aSrobert     _M_wordwrap = true;
499404b540aSrobert     _M_print_word("error: ");
500404b540aSrobert 
501404b540aSrobert     // Print the error message
502404b540aSrobert     assert(_M_text);
503404b540aSrobert     _M_print_string(_M_text);
504404b540aSrobert     _M_print_word(".\n");
505404b540aSrobert 
506404b540aSrobert     // Emit descriptions of the objects involved in the operation
507404b540aSrobert     _M_wordwrap = false;
508404b540aSrobert     bool __has_noninteger_parameters = false;
509404b540aSrobert     for (unsigned int __i = 0; __i < _M_num_parameters; ++__i)
510404b540aSrobert       {
511404b540aSrobert 	if (_M_parameters[__i]._M_kind == _Parameter::__iterator
512404b540aSrobert 	    || _M_parameters[__i]._M_kind == _Parameter::__sequence)
513404b540aSrobert 	  {
514404b540aSrobert 	    if (!__has_noninteger_parameters)
515404b540aSrobert 	      {
516404b540aSrobert 		_M_first_line = true;
517404b540aSrobert 		_M_print_word("\nObjects involved in the operation:\n");
518404b540aSrobert 		__has_noninteger_parameters = true;
519404b540aSrobert 	      }
520404b540aSrobert 	    _M_parameters[__i]._M_print_description(this);
521404b540aSrobert 	  }
522404b540aSrobert       }
523404b540aSrobert 
524404b540aSrobert     abort();
525404b540aSrobert   }
526404b540aSrobert 
527404b540aSrobert   template<typename _Tp>
528404b540aSrobert     void
_M_format_word(char * __buf,int __n,const char * __fmt,_Tp __s) const529404b540aSrobert     _Error_formatter::_M_format_word(char* __buf,
530404b540aSrobert 				     int __n __attribute__ ((__unused__)),
531404b540aSrobert 				     const char* __fmt, _Tp __s) const
532404b540aSrobert     {
533404b540aSrobert #ifdef _GLIBCXX_USE_C99
534404b540aSrobert       std::snprintf(__buf, __n, __fmt, __s);
535404b540aSrobert #else
536404b540aSrobert       std::sprintf(__buf, __fmt, __s);
537404b540aSrobert #endif
538404b540aSrobert     }
539404b540aSrobert 
540404b540aSrobert 
541404b540aSrobert   void
_M_print_word(const char * __word) const542404b540aSrobert   _Error_formatter::_M_print_word(const char* __word) const
543404b540aSrobert   {
544404b540aSrobert     if (!_M_wordwrap)
545404b540aSrobert       {
546404b540aSrobert 	fprintf(stderr, "%s", __word);
547404b540aSrobert 	return;
548404b540aSrobert       }
549404b540aSrobert 
550404b540aSrobert     size_t __length = strlen(__word);
551404b540aSrobert     if (__length == 0)
552404b540aSrobert       return;
553404b540aSrobert 
554404b540aSrobert     if ((_M_column + __length < _M_max_length)
555404b540aSrobert 	|| (__length >= _M_max_length && _M_column == 1))
556404b540aSrobert       {
557404b540aSrobert 	// If this isn't the first line, indent
558404b540aSrobert 	if (_M_column == 1 && !_M_first_line)
559404b540aSrobert 	  {
560404b540aSrobert 	    char __spacing[_M_indent + 1];
561404b540aSrobert 	    for (int i = 0; i < _M_indent; ++i)
562404b540aSrobert 	      __spacing[i] = ' ';
563404b540aSrobert 	    __spacing[_M_indent] = '\0';
564404b540aSrobert 	    fprintf(stderr, "%s", __spacing);
565404b540aSrobert 	    _M_column += _M_indent;
566404b540aSrobert 	  }
567404b540aSrobert 
568404b540aSrobert 	fprintf(stderr, "%s", __word);
569404b540aSrobert 	_M_column += __length;
570404b540aSrobert 
571404b540aSrobert 	if (__word[__length - 1] == '\n')
572404b540aSrobert 	  {
573404b540aSrobert 	    _M_first_line = false;
574404b540aSrobert 	    _M_column = 1;
575404b540aSrobert 	  }
576404b540aSrobert       }
577404b540aSrobert     else
578404b540aSrobert       {
579404b540aSrobert 	_M_column = 1;
580404b540aSrobert 	_M_print_word("\n");
581404b540aSrobert 	_M_print_word(__word);
582404b540aSrobert       }
583404b540aSrobert   }
584404b540aSrobert 
585404b540aSrobert   void
586404b540aSrobert   _Error_formatter::
_M_print_string(const char * __string) const587404b540aSrobert   _M_print_string(const char* __string) const
588404b540aSrobert   {
589404b540aSrobert     const char* __start = __string;
590404b540aSrobert     const char* __finish = __start;
591404b540aSrobert     const int __bufsize = 128;
592404b540aSrobert     char __buf[__bufsize];
593404b540aSrobert 
594404b540aSrobert     while (*__start)
595404b540aSrobert       {
596404b540aSrobert 	if (*__start != '%')
597404b540aSrobert 	  {
598404b540aSrobert 	    // [__start, __finish) denotes the next word
599404b540aSrobert 	    __finish = __start;
600404b540aSrobert 	    while (isalnum(*__finish))
601404b540aSrobert 	      ++__finish;
602404b540aSrobert 	    if (__start == __finish)
603404b540aSrobert 	      ++__finish;
604404b540aSrobert 	    if (isspace(*__finish))
605404b540aSrobert 	      ++__finish;
606404b540aSrobert 
607404b540aSrobert 	    const ptrdiff_t __len = __finish - __start;
608404b540aSrobert 	    assert(__len < __bufsize);
609404b540aSrobert 	    memcpy(__buf, __start, __len);
610404b540aSrobert 	    __buf[__len] = '\0';
611404b540aSrobert 	    _M_print_word(__buf);
612404b540aSrobert 	    __start = __finish;
613404b540aSrobert 
614404b540aSrobert 	    // Skip extra whitespace
615404b540aSrobert 	    while (*__start == ' ')
616404b540aSrobert 	      ++__start;
617404b540aSrobert 
618404b540aSrobert 	    continue;
619404b540aSrobert 	  }
620404b540aSrobert 
621404b540aSrobert 	++__start;
622404b540aSrobert 	assert(*__start);
623404b540aSrobert 	if (*__start == '%')
624404b540aSrobert 	  {
625404b540aSrobert 	    _M_print_word("%");
626404b540aSrobert 	    ++__start;
627404b540aSrobert 	    continue;
628404b540aSrobert 	  }
629404b540aSrobert 
630404b540aSrobert 	// Get the parameter number
631404b540aSrobert 	assert(*__start >= '1' && *__start <= '9');
632404b540aSrobert 	size_t __param = *__start - '0';
633404b540aSrobert 	--__param;
634404b540aSrobert 	assert(__param < _M_num_parameters);
635404b540aSrobert 
636404b540aSrobert 	// '.' separates the parameter number from the field
637404b540aSrobert 	// name, if there is one.
638404b540aSrobert 	++__start;
639404b540aSrobert 	if (*__start != '.')
640404b540aSrobert 	  {
641404b540aSrobert 	    assert(*__start == ';');
642404b540aSrobert 	    ++__start;
643404b540aSrobert 	    __buf[0] = '\0';
644404b540aSrobert 	    if (_M_parameters[__param]._M_kind == _Parameter::__integer)
645404b540aSrobert 	      {
646404b540aSrobert 		_M_format_word(__buf, __bufsize, "%ld",
647404b540aSrobert 			       _M_parameters[__param]._M_variant._M_integer._M_value);
648404b540aSrobert 		_M_print_word(__buf);
649404b540aSrobert 	      }
650404b540aSrobert 	    else if (_M_parameters[__param]._M_kind == _Parameter::__string)
651404b540aSrobert 	      _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value);
652404b540aSrobert 	    continue;
653404b540aSrobert 	  }
654404b540aSrobert 
655404b540aSrobert 	// Extract the field name we want
656404b540aSrobert 	enum { __max_field_len = 16 };
657404b540aSrobert 	char __field[__max_field_len];
658404b540aSrobert 	int __field_idx = 0;
659404b540aSrobert 	++__start;
660404b540aSrobert 	while (*__start != ';')
661404b540aSrobert 	  {
662404b540aSrobert 	    assert(*__start);
663404b540aSrobert 	    assert(__field_idx < __max_field_len-1);
664404b540aSrobert 	    __field[__field_idx++] = *__start++;
665404b540aSrobert 	  }
666404b540aSrobert 	++__start;
667404b540aSrobert 	__field[__field_idx] = 0;
668404b540aSrobert 
669404b540aSrobert 	_M_parameters[__param]._M_print_field(this, __field);
670404b540aSrobert       }
671404b540aSrobert   }
672404b540aSrobert 
673404b540aSrobert   // Instantiations.
674404b540aSrobert   template
675404b540aSrobert     void
676404b540aSrobert     _Error_formatter::_M_format_word(char*, int, const char*,
677404b540aSrobert 				     const void*) const;
678404b540aSrobert 
679404b540aSrobert   template
680404b540aSrobert     void
681404b540aSrobert     _Error_formatter::_M_format_word(char*, int, const char*, long) const;
682404b540aSrobert 
683404b540aSrobert   template
684404b540aSrobert     void
685404b540aSrobert     _Error_formatter::_M_format_word(char*, int, const char*,
686404b540aSrobert 				     std::size_t) const;
687404b540aSrobert 
688404b540aSrobert   template
689404b540aSrobert     void
690404b540aSrobert     _Error_formatter::_M_format_word(char*, int, const char*,
691404b540aSrobert 				     const char*) const;
692404b540aSrobert } // namespace __gnu_debug
693