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