// Debugging mode support code -*- C++ -*-
-// Copyright (C) 2003
+// Copyright (C) 2003, 2004, 2005, 2006, 2007
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
-// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
// USA.
// As a special exception, you may use this file as part of a free software
#include <debug/safe_sequence.h>
#include <debug/safe_iterator.h>
#include <algorithm>
-#include <cstdlib>
#include <cassert>
#include <cstring>
-#include <cstdio>
#include <cctype>
+#include <cstdio>
+#include <cstdlib>
using namespace std;
+namespace
+{
+ __gnu_cxx::__mutex safe_base_mutex;
+} // anonymous namespace
+
namespace __gnu_debug
{
const char* _S_debug_messages[] =
"attempt to increment an end-of-stream istreambuf_iterator"
};
- void
+ void
_Safe_sequence_base::
_M_detach_all()
{
- for (_Safe_iterator_base* iter = _M_iterators; iter; )
+ __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
+ for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
{
- _Safe_iterator_base* old = iter;
- iter = iter->_M_next;
- old->_M_attach(0, false);
+ _Safe_iterator_base* __old = __iter;
+ __iter = __iter->_M_next;
+ __old->_M_detach_single();
}
- for (_Safe_iterator_base* iter = _M_const_iterators; iter; )
+ for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
{
- _Safe_iterator_base* old = iter;
- iter = iter->_M_next;
- old->_M_attach(0, true);
+ _Safe_iterator_base* __old = __iter2;
+ __iter2 = __iter2->_M_next;
+ __old->_M_detach_single();
}
}
- void
+ void
_Safe_sequence_base::
_M_detach_singular()
{
- for (_Safe_iterator_base* iter = _M_iterators; iter; )
+ __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
+ for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
{
- _Safe_iterator_base* old = iter;
- iter = iter->_M_next;
- if (old->_M_singular())
- old->_M_attach(0, false);
+ _Safe_iterator_base* __old = __iter;
+ __iter = __iter->_M_next;
+ if (__old->_M_singular())
+ __old->_M_detach_single();
}
- for (_Safe_iterator_base* iter = _M_const_iterators; iter; )
+ for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
{
- _Safe_iterator_base* old = iter;
- iter = iter->_M_next;
- if (old->_M_singular())
- old->_M_attach(0, true);
+ _Safe_iterator_base* __old = __iter2;
+ __iter2 = __iter2->_M_next;
+ if (__old->_M_singular())
+ __old->_M_detach_single();
}
}
-
- void
+
+ void
_Safe_sequence_base::
_M_revalidate_singular()
{
- _Safe_iterator_base* iter;
- for (iter = _M_iterators; iter; iter = iter->_M_next)
- {
- iter->_M_version = _M_version;
- iter = iter->_M_next;
- }
-
- for (iter = _M_const_iterators; iter; iter = iter->_M_next)
- {
- iter->_M_version = _M_version;
- iter = iter->_M_next;
- }
+ __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
+ for (_Safe_iterator_base* __iter = _M_iterators; __iter;
+ __iter = __iter->_M_next)
+ __iter->_M_version = _M_version;
+
+ for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
+ __iter2 = __iter2->_M_next)
+ __iter2->_M_version = _M_version;
}
- void
+ void
_Safe_sequence_base::
_M_swap(_Safe_sequence_base& __x)
{
+ __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
swap(_M_iterators, __x._M_iterators);
swap(_M_const_iterators, __x._M_const_iterators);
swap(_M_version, __x._M_version);
- _Safe_iterator_base* iter;
- for (iter = _M_iterators; iter; iter = iter->_M_next)
- iter->_M_sequence = this;
- for (iter = __x._M_iterators; iter; iter = iter->_M_next)
- iter->_M_sequence = &__x;
- for (iter = _M_const_iterators; iter; iter = iter->_M_next)
- iter->_M_sequence = this;
- for (iter = __x._M_const_iterators; iter; iter = iter->_M_next)
- iter->_M_sequence = &__x;
+ _Safe_iterator_base* __iter;
+ for (__iter = _M_iterators; __iter; __iter = __iter->_M_next)
+ __iter->_M_sequence = this;
+ for (__iter = __x._M_iterators; __iter; __iter = __iter->_M_next)
+ __iter->_M_sequence = &__x;
+ for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next)
+ __iter->_M_sequence = this;
+ for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next)
+ __iter->_M_sequence = &__x;
}
-
- void
+
+ __gnu_cxx::__mutex&
+ _Safe_sequence_base::
+ _M_get_mutex()
+ { return safe_base_mutex; }
+
+ void
_Safe_iterator_base::
_M_attach(_Safe_sequence_base* __seq, bool __constant)
{
- _M_detach();
+ __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
+ _M_attach_single(__seq, __constant);
+ }
+
+ void
+ _Safe_iterator_base::
+ _M_attach_single(_Safe_sequence_base* __seq, bool __constant)
+ {
+ _M_detach_single();
// Attach to the new sequence (if there is one)
if (__seq)
}
}
- void
+ void
_Safe_iterator_base::
_M_detach()
{
+ __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
+ _M_detach_single();
+ }
+
+ void
+ _Safe_iterator_base::
+ _M_detach_single()
+ {
if (_M_sequence)
{
// Remove us from this sequence's list
_M_prior = 0;
_M_next = 0;
}
-
+
bool
_Safe_iterator_base::
_M_singular() const
_Safe_iterator_base::
_M_can_compare(const _Safe_iterator_base& __x) const
{
- return (!_M_singular() && !__x._M_singular()
- && _M_sequence == __x._M_sequence);
+ return (!_M_singular()
+ && !__x._M_singular() && _M_sequence == __x._M_sequence);
}
+ __gnu_cxx::__mutex&
+ _Safe_iterator_base::
+ _M_get_mutex()
+ { return safe_base_mutex; }
+
void
_Error_formatter::_Parameter::
_M_print_field(const _Error_formatter* __formatter, const char* __name) const
{
assert(this->_M_kind != _Parameter::__unused_param);
- const int bufsize = 64;
- char buf[bufsize];
+ const int __bufsize = 64;
+ char __buf[__bufsize];
if (_M_kind == __iterator)
{
}
else if (strcmp(__name, "address") == 0)
{
- __formatter->_M_format_word(buf, bufsize, "%p",
+ __formatter->_M_format_word(__buf, __bufsize, "%p",
_M_variant._M_iterator._M_address);
- __formatter->_M_print_word(buf);
+ __formatter->_M_print_word(__buf);
}
else if (strcmp(__name, "type") == 0)
{
else if (strcmp(__name, "sequence") == 0)
{
assert(_M_variant._M_iterator._M_sequence);
- __formatter->_M_format_word(buf, bufsize, "%p",
+ __formatter->_M_format_word(__buf, __bufsize, "%p",
_M_variant._M_iterator._M_sequence);
- __formatter->_M_print_word(buf);
+ __formatter->_M_print_word(__buf);
}
else if (strcmp(__name, "seq_type") == 0)
{
else if (strcmp(__name, "address") == 0)
{
assert(_M_variant._M_sequence._M_address);
- __formatter->_M_format_word(buf, bufsize, "%p",
+ __formatter->_M_format_word(__buf, __bufsize, "%p",
_M_variant._M_sequence._M_address);
- __formatter->_M_print_word(buf);
+ __formatter->_M_print_word(__buf);
}
else if (strcmp(__name, "type") == 0)
{
_Error_formatter::_Parameter::
_M_print_description(const _Error_formatter* __formatter) const
{
- const int bufsize = 128;
- char buf[bufsize];
+ const int __bufsize = 128;
+ char __buf[__bufsize];
if (_M_kind == __iterator)
{
__formatter->_M_print_word("iterator ");
if (_M_variant._M_iterator._M_name)
{
- __formatter->_M_format_word(buf, bufsize, "\"%s\" ",
+ __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
_M_variant._M_iterator._M_name);
- __formatter->_M_print_word(buf);
+ __formatter->_M_print_word(__buf);
}
- __formatter->_M_format_word(buf, bufsize, "@ 0x%p {\n",
+ __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
_M_variant._M_iterator._M_address);
- __formatter->_M_print_word(buf);
+ __formatter->_M_print_word(__buf);
if (_M_variant._M_iterator._M_type)
{
__formatter->_M_print_word("type = ");
__formatter->_M_print_word("' ");
}
- __formatter->_M_format_word(buf, bufsize, "@ 0x%p\n",
+ __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n",
_M_variant._M_sequence._M_address);
- __formatter->_M_print_word(buf);
+ __formatter->_M_print_word(__buf);
}
__formatter->_M_print_word("}\n");
}
__formatter->_M_print_word("sequence ");
if (_M_variant._M_sequence._M_name)
{
- __formatter->_M_format_word(buf, bufsize, "\"%s\" ",
+ __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
_M_variant._M_sequence._M_name);
- __formatter->_M_print_word(buf);
+ __formatter->_M_print_word(__buf);
}
- __formatter->_M_format_word(buf, bufsize, "@ 0x%p {\n",
+ __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
_M_variant._M_sequence._M_address);
- __formatter->_M_print_word(buf);
+ __formatter->_M_print_word(__buf);
if (_M_variant._M_sequence._M_type)
{
void
_Error_formatter::_M_error() const
{
- const int bufsize = 128;
- char buf[bufsize];
+ const int __bufsize = 128;
+ char __buf[__bufsize];
// Emit file & line number information
_M_column = 1;
_M_wordwrap = false;
if (_M_file)
{
- _M_format_word(buf, bufsize, "%s:", _M_file);
- _M_print_word(buf);
- _M_column += strlen(buf);
+ _M_format_word(__buf, __bufsize, "%s:", _M_file);
+ _M_print_word(__buf);
+ _M_column += strlen(__buf);
}
if (_M_line > 0)
{
- _M_format_word(buf, bufsize, "%u:", _M_line);
- _M_print_word(buf);
- _M_column += strlen(buf);
+ _M_format_word(__buf, __bufsize, "%u:", _M_line);
+ _M_print_word(__buf);
+ _M_column += strlen(__buf);
}
- _M_wordwrap = true;
+ if (_M_max_length)
+ _M_wordwrap = true;
_M_print_word("error: ");
// Print the error message
// Emit descriptions of the objects involved in the operation
_M_wordwrap = false;
- bool has_noninteger_parameters = false;
- for (unsigned int i = 0; i < _M_num_parameters; ++i)
+ bool __has_noninteger_parameters = false;
+ for (unsigned int __i = 0; __i < _M_num_parameters; ++__i)
{
- if (_M_parameters[i]._M_kind == _Parameter::__iterator
- || _M_parameters[i]._M_kind == _Parameter::__sequence)
+ if (_M_parameters[__i]._M_kind == _Parameter::__iterator
+ || _M_parameters[__i]._M_kind == _Parameter::__sequence)
{
- if (!has_noninteger_parameters)
+ if (!__has_noninteger_parameters)
{
_M_first_line = true;
_M_print_word("\nObjects involved in the operation:\n");
- has_noninteger_parameters = true;
+ __has_noninteger_parameters = true;
}
- _M_parameters[i]._M_print_description(this);
+ _M_parameters[__i]._M_print_description(this);
}
}
template<typename _Tp>
void
_Error_formatter::_M_format_word(char* __buf,
- int __n __attribute__((__unused__)),
+ int __n __attribute__ ((__unused__)),
const char* __fmt, _Tp __s) const
{
#ifdef _GLIBCXX_USE_C99
// If this isn't the first line, indent
if (_M_column == 1 && !_M_first_line)
{
- char spacing[_M_indent + 1];
+ char __spacing[_M_indent + 1];
for (int i = 0; i < _M_indent; ++i)
- spacing[i] = ' ';
- spacing[_M_indent] = '\0';
- fprintf(stderr, "%s", spacing);
+ __spacing[i] = ' ';
+ __spacing[_M_indent] = '\0';
+ fprintf(stderr, "%s", __spacing);
_M_column += _M_indent;
}
_M_print_string(const char* __string) const
{
const char* __start = __string;
- const char* __end = __start;
- const int bufsize = 128;
- char buf[bufsize];
+ const char* __finish = __start;
+ const int __bufsize = 128;
+ char __buf[__bufsize];
while (*__start)
{
if (*__start != '%')
{
- // [__start, __end) denotes the next word
- __end = __start;
- while (isalnum(*__end)) ++__end;
- if (__start == __end) ++__end;
- if (isspace(*__end)) ++__end;
+ // [__start, __finish) denotes the next word
+ __finish = __start;
+ while (isalnum(*__finish))
+ ++__finish;
+ if (__start == __finish)
+ ++__finish;
+ if (isspace(*__finish))
+ ++__finish;
- assert(__end - __start + 1< bufsize);
- _M_format_word(buf, __end - __start + 1, "%s", __start);
- _M_print_word(buf);
- __start = __end;
+ const ptrdiff_t __len = __finish - __start;
+ assert(__len < __bufsize);
+ memcpy(__buf, __start, __len);
+ __buf[__len] = '\0';
+ _M_print_word(__buf);
+ __start = __finish;
// Skip extra whitespace
while (*__start == ' ')
continue;
}
- ++__start;
- assert(*__start);
- if (*__start == '%')
- {
- _M_print_word("%");
- ++__start;
- continue;
- }
-
- // Get the parameter number
- assert(*__start >= '1' && *__start <= '9');
- size_t param = *__start - '0';
- --param;
- assert(param < _M_num_parameters);
+ ++__start;
+ assert(*__start);
+ if (*__start == '%')
+ {
+ _M_print_word("%");
+ ++__start;
+ continue;
+ }
+
+ // Get the parameter number
+ assert(*__start >= '1' && *__start <= '9');
+ size_t __param = *__start - '0';
+ --__param;
+ assert(__param < _M_num_parameters);
- // '.' separates the parameter number from the field
- // name, if there is one.
- ++__start;
- if (*__start != '.')
- {
- assert(*__start == ';');
+ // '.' separates the parameter number from the field
+ // name, if there is one.
++__start;
- buf[0] = '\0';
- if (_M_parameters[param]._M_kind == _Parameter::__integer)
- {
- _M_format_word(buf, bufsize, "%ld",
- _M_parameters[param]._M_variant._M_integer._M_value);
- _M_print_word(buf);
- }
- else if (_M_parameters[param]._M_kind == _Parameter::__string)
- _M_print_string(_M_parameters[param]._M_variant._M_string._M_value);
- continue;
+ if (*__start != '.')
+ {
+ assert(*__start == ';');
+ ++__start;
+ __buf[0] = '\0';
+ if (_M_parameters[__param]._M_kind == _Parameter::__integer)
+ {
+ _M_format_word(__buf, __bufsize, "%ld",
+ _M_parameters[__param]._M_variant._M_integer._M_value);
+ _M_print_word(__buf);
+ }
+ else if (_M_parameters[__param]._M_kind == _Parameter::__string)
+ _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value);
+ continue;
+ }
+
+ // Extract the field name we want
+ enum { __max_field_len = 16 };
+ char __field[__max_field_len];
+ int __field_idx = 0;
+ ++__start;
+ while (*__start != ';')
+ {
+ assert(*__start);
+ assert(__field_idx < __max_field_len-1);
+ __field[__field_idx++] = *__start++;
+ }
+ ++__start;
+ __field[__field_idx] = 0;
+
+ _M_parameters[__param]._M_print_field(this, __field);
}
-
- // Extract the field name we want
- enum { max_field_len = 16 };
- char field[max_field_len];
- int field_idx = 0;
- ++__start;
- while (*__start != ';')
+ }
+
+ void
+ _Error_formatter::_M_get_max_length() const
+ {
+ const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
+ if (__nptr)
{
- assert(*__start);
- assert(field_idx < max_field_len-1);
- field[field_idx++] = *__start++;
+ char* __endptr;
+ const unsigned long __ret = std::strtoul(__nptr, &__endptr, 0);
+ if (*__nptr != '\0' && *__endptr == '\0')
+ _M_max_length = __ret;
}
- ++__start;
- field[field_idx] = 0;
-
- _M_parameters[param]._M_print_field(this, field);
- }
}
// Instantiations.
template
void
- _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt,
- const void* __s) const;
+ _Error_formatter::_M_format_word(char*, int, const char*,
+ const void*) const;
template
void
- _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt,
- long __s) const;
+ _Error_formatter::_M_format_word(char*, int, const char*, long) const;
template
void
- _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt,
- std::size_t __s) const;
+ _Error_formatter::_M_format_word(char*, int, const char*,
+ std::size_t) const;
template
void
- _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt,
- const char* __s) const;
+ _Error_formatter::_M_format_word(char*, int, const char*,
+ const char*) const;
} // namespace __gnu_debug