Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Debugging mode support code -*- C++ -*-
  2.  
  3. // Copyright (C) 2003-2013 Free Software Foundation, Inc.
  4. //
  5. // This file is part of the GNU ISO C++ Library.  This library is free
  6. // software; you can redistribute it and/or modify it under the
  7. // terms of the GNU General Public License as published by the
  8. // Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10.  
  11. // This library is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15.  
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. #include <debug/debug.h>
  26. #include <debug/safe_sequence.h>
  27. #include <debug/safe_unordered_container.h>
  28. #include <debug/safe_iterator.h>
  29. #include <debug/safe_local_iterator.h>
  30. #include <algorithm>
  31. #include <cassert>
  32. #include <cstring>
  33. #include <cctype>
  34. #include <cstdio>
  35. #include <cstdlib>
  36. #include <functional>
  37.  
  38. using namespace std;
  39.  
  40. namespace
  41. {
  42.   /** Returns different instances of __mutex depending on the passed address
  43.    *  in order to limit contention without breaking current library binary
  44.    *  compatibility. */
  45.   __gnu_cxx::__mutex&
  46.   get_safe_base_mutex(void* __address)
  47.   {
  48.     const size_t mask = 0xf;
  49.     static __gnu_cxx::__mutex safe_base_mutex[mask + 1];
  50.     const size_t index = _Hash_impl::hash(__address) & mask;
  51.     return safe_base_mutex[index];
  52.   }
  53.  
  54.   void
  55.   swap_its(__gnu_debug::_Safe_sequence_base& __lhs,
  56.            __gnu_debug::_Safe_iterator_base*& __lhs_its,
  57.            __gnu_debug::_Safe_sequence_base& __rhs,
  58.            __gnu_debug::_Safe_iterator_base*& __rhs_its)
  59.   {
  60.     swap(__lhs_its, __rhs_its);
  61.     __gnu_debug::_Safe_iterator_base* __iter;
  62.     for (__iter = __rhs_its; __iter; __iter = __iter->_M_next)
  63.       __iter->_M_sequence = &__rhs;
  64.     for (__iter = __lhs_its; __iter; __iter = __iter->_M_next)
  65.       __iter->_M_sequence = &__lhs;
  66.   }
  67.  
  68.   void
  69.   swap_seq(__gnu_debug::_Safe_sequence_base& __lhs,
  70.            __gnu_debug::_Safe_sequence_base& __rhs)
  71.   {
  72.     swap(__lhs._M_version, __rhs._M_version);
  73.     swap_its(__lhs, __lhs._M_iterators,
  74.              __rhs, __rhs._M_iterators);
  75.     swap_its(__lhs, __lhs._M_const_iterators,
  76.              __rhs, __rhs._M_const_iterators);
  77.   }
  78.  
  79.   void
  80.   swap_ucont(__gnu_debug::_Safe_unordered_container_base& __lhs,
  81.             __gnu_debug::_Safe_unordered_container_base& __rhs)
  82.   {
  83.     swap_seq(__lhs, __rhs);
  84.     swap_its(__lhs, __lhs._M_local_iterators,
  85.              __rhs, __rhs._M_local_iterators);
  86.     swap_its(__lhs, __lhs._M_const_local_iterators,
  87.              __rhs, __rhs._M_const_local_iterators);
  88.   }
  89.  
  90.   void
  91.   detach_all(__gnu_debug::_Safe_iterator_base* __iter)
  92.   {
  93.     for (; __iter;)
  94.       {
  95.         __gnu_debug::_Safe_iterator_base* __old = __iter;
  96.         __iter = __iter->_M_next;
  97.         __old->_M_reset();
  98.       }
  99.   }
  100. } // anonymous namespace
  101.  
  102. namespace __gnu_debug
  103. {
  104.   const char* _S_debug_messages[] =
  105.   {
  106.     // General Checks
  107.     "function requires a valid iterator range [%1.name;, %2.name;)",
  108.     "attempt to insert into container with a singular iterator",
  109.     "attempt to insert into container with an iterator"
  110.     " from a different container",
  111.     "attempt to erase from container with a %2.state; iterator",
  112.     "attempt to erase from container with an iterator"
  113.     " from a different container",
  114.     "attempt to subscript container with out-of-bounds index %2;,"
  115.     " but container only holds %3; elements",
  116.     "attempt to access an element in an empty container",
  117.     "elements in iterator range [%1.name;, %2.name;)"
  118.     " are not partitioned by the value %3;",
  119.     "elements in iterator range [%1.name;, %2.name;)"
  120.     " are not partitioned by the predicate %3; and value %4;",
  121.     "elements in iterator range [%1.name;, %2.name;) are not sorted",
  122.     "elements in iterator range [%1.name;, %2.name;)"
  123.     " are not sorted according to the predicate %3;",
  124.     "elements in iterator range [%1.name;, %2.name;) do not form a heap",
  125.     "elements in iterator range [%1.name;, %2.name;)"
  126.     " do not form a heap with respect to the predicate %3;",
  127.     // std::bitset checks
  128.     "attempt to write through a singular bitset reference",
  129.     "attempt to read from a singular bitset reference",
  130.     "attempt to flip a singular bitset reference",
  131.     // std::list checks
  132.     "attempt to splice a list into itself",
  133.     "attempt to splice lists with unequal allocators",
  134.     "attempt to splice elements referenced by a %1.state; iterator",
  135.     "attempt to splice an iterator from a different container",
  136.     "splice destination %1.name;"
  137.     " occurs within source range [%2.name;, %3.name;)",
  138.     // iterator checks
  139.     "attempt to initialize an iterator that will immediately become singular",
  140.     "attempt to copy-construct an iterator from a singular iterator",
  141.     "attempt to construct a constant iterator"
  142.     " from a singular mutable iterator",
  143.     "attempt to copy from a singular iterator",
  144.     "attempt to dereference a %1.state; iterator",
  145.     "attempt to increment a %1.state; iterator",
  146.     "attempt to decrement a %1.state; iterator",
  147.     "attempt to subscript a %1.state; iterator %2; step from"
  148.     " its current position, which falls outside its dereferenceable range",
  149.     "attempt to advance a %1.state; iterator %2; steps,"
  150.     " which falls outside its valid range",
  151.     "attempt to retreat a %1.state; iterator %2; steps,"
  152.     " which falls outside its valid range",
  153.     "attempt to compare a %1.state; iterator to a %2.state; iterator",
  154.     "attempt to compare iterators from different sequences",
  155.     "attempt to order a %1.state; iterator to a %2.state; iterator",
  156.     "attempt to order iterators from different sequences",
  157.     "attempt to compute the difference between a %1.state;"
  158.     " iterator to a %2.state; iterator",
  159.     "attempt to compute the different between two iterators"
  160.     " from different sequences",
  161.     // istream_iterator
  162.     "attempt to dereference an end-of-stream istream_iterator",
  163.     "attempt to increment an end-of-stream istream_iterator",
  164.     // ostream_iterator
  165.     "attempt to output via an ostream_iterator with no associated stream",
  166.     // istreambuf_iterator
  167.     "attempt to dereference an end-of-stream istreambuf_iterator"
  168.     " (this is a GNU extension)",
  169.     "attempt to increment an end-of-stream istreambuf_iterator",
  170.     // std::forward_list
  171.     "attempt to insert into container after an end iterator",
  172.     "attempt to erase from container after a %2.state; iterator not followed"
  173.     " by a dereferenceable one",
  174.     "function requires a valid iterator range (%2.name;, %3.name;)"
  175.     ", \"%2.name;\" shall be before and not equal to \"%3.name;\"",
  176.     // std::unordered_container::local_iterator
  177.     "attempt to compare local iterators from different unordered container"
  178.     " buckets",
  179.     "function requires a non-empty iterator range [%1.name;, %2.name;)",
  180.     "attempt to self move assign",
  181.     "attempt to access container with out-of-bounds bucket index %2;,"
  182.     " container only holds %3; buckets",
  183.     "load factor shall be positive",
  184.     "allocators must be equal"
  185.   };
  186.  
  187.   void
  188.   _Safe_sequence_base::
  189.   _M_detach_all()
  190.   {
  191.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  192.     detach_all(_M_iterators);
  193.     _M_iterators = 0;
  194.    
  195.     detach_all(_M_const_iterators);
  196.     _M_const_iterators = 0;
  197.   }
  198.  
  199.   void
  200.   _Safe_sequence_base::
  201.   _M_detach_singular()
  202.   {
  203.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  204.     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
  205.       {
  206.         _Safe_iterator_base* __old = __iter;
  207.         __iter = __iter->_M_next;
  208.         if (__old->_M_singular())
  209.           __old->_M_detach_single();
  210.       }
  211.  
  212.     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
  213.       {
  214.         _Safe_iterator_base* __old = __iter2;
  215.         __iter2 = __iter2->_M_next;
  216.         if (__old->_M_singular())
  217.           __old->_M_detach_single();
  218.       }
  219.   }
  220.  
  221.   void
  222.   _Safe_sequence_base::
  223.   _M_revalidate_singular()
  224.   {
  225.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  226.     for (_Safe_iterator_base* __iter = _M_iterators; __iter;
  227.          __iter = __iter->_M_next)
  228.       __iter->_M_version = _M_version;
  229.  
  230.     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
  231.          __iter2 = __iter2->_M_next)
  232.       __iter2->_M_version = _M_version;
  233.   }
  234.  
  235.   void
  236.   _Safe_sequence_base::
  237.   _M_swap(_Safe_sequence_base& __x)
  238.   {
  239.     // We need to lock both sequences to swap
  240.     using namespace __gnu_cxx;
  241.     __mutex *__this_mutex = &_M_get_mutex();
  242.     __mutex *__x_mutex = &__x._M_get_mutex();
  243.     if (__this_mutex == __x_mutex)
  244.       {
  245.         __scoped_lock __lock(*__this_mutex);
  246.         swap_seq(*this, __x);
  247.       }
  248.     else
  249.       {
  250.         __scoped_lock __l1(__this_mutex < __x_mutex
  251.                              ? *__this_mutex : *__x_mutex);
  252.         __scoped_lock __l2(__this_mutex < __x_mutex
  253.                              ? *__x_mutex : *__this_mutex);
  254.         swap_seq(*this, __x);
  255.       }
  256.   }
  257.  
  258.   __gnu_cxx::__mutex&
  259.   _Safe_sequence_base::
  260.   _M_get_mutex() throw ()
  261.   { return get_safe_base_mutex(this); }
  262.  
  263.   void
  264.   _Safe_sequence_base::
  265.   _M_attach(_Safe_iterator_base* __it, bool __constant)
  266.   {
  267.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  268.     _M_attach_single(__it, __constant);
  269.   }
  270.  
  271.   void
  272.   _Safe_sequence_base::
  273.   _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ()
  274.   {
  275.     _Safe_iterator_base*& __its =
  276.       __constant ? _M_const_iterators : _M_iterators;
  277.     __it->_M_next = __its;
  278.     if (__it->_M_next)
  279.       __it->_M_next->_M_prior = __it;
  280.     __its = __it;
  281.   }
  282.  
  283.   void
  284.   _Safe_sequence_base::
  285.   _M_detach(_Safe_iterator_base* __it)
  286.   {
  287.     // Remove __it from this sequence's list
  288.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  289.     _M_detach_single(__it);
  290.   }
  291.  
  292.   void
  293.   _Safe_sequence_base::
  294.   _M_detach_single(_Safe_iterator_base* __it) throw ()
  295.   {
  296.     // Remove __it from this sequence's list
  297.     __it->_M_unlink();
  298.     if (_M_const_iterators == __it)
  299.       _M_const_iterators = __it->_M_next;
  300.     if (_M_iterators == __it)
  301.       _M_iterators = __it->_M_next;
  302.   }
  303.  
  304.   void
  305.   _Safe_iterator_base::
  306.   _M_attach(_Safe_sequence_base* __seq, bool __constant)
  307.   {
  308.     _M_detach();
  309.    
  310.     // Attach to the new sequence (if there is one)
  311.     if (__seq)
  312.       {
  313.         _M_sequence = __seq;
  314.         _M_version = _M_sequence->_M_version;
  315.         _M_sequence->_M_attach(this, __constant);
  316.       }
  317.   }
  318.  
  319.   void
  320.   _Safe_iterator_base::
  321.   _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ()
  322.   {
  323.     _M_detach_single();
  324.    
  325.     // Attach to the new sequence (if there is one)
  326.     if (__seq)
  327.       {
  328.         _M_sequence = __seq;
  329.         _M_version = _M_sequence->_M_version;
  330.         _M_sequence->_M_attach_single(this, __constant);
  331.       }
  332.   }
  333.  
  334.   void
  335.   _Safe_iterator_base::
  336.   _M_detach()
  337.   {
  338.     if (_M_sequence)
  339.       _M_sequence->_M_detach(this);
  340.  
  341.     _M_reset();
  342.   }
  343.  
  344.   void
  345.   _Safe_iterator_base::
  346.   _M_detach_single() throw ()
  347.   {
  348.     if (_M_sequence)
  349.       _M_sequence->_M_detach_single(this);
  350.  
  351.     _M_reset();
  352.   }
  353.  
  354.   void
  355.   _Safe_iterator_base::
  356.   _M_reset() throw ()
  357.   {
  358.     _M_sequence = 0;
  359.     _M_version = 0;
  360.     _M_prior = 0;
  361.     _M_next = 0;
  362.   }
  363.  
  364.   bool
  365.   _Safe_iterator_base::
  366.   _M_singular() const throw ()
  367.   { return !_M_sequence || _M_version != _M_sequence->_M_version; }
  368.    
  369.   bool
  370.   _Safe_iterator_base::
  371.   _M_can_compare(const _Safe_iterator_base& __x) const throw ()
  372.   {
  373.     return (!_M_singular()
  374.             && !__x._M_singular() && _M_sequence == __x._M_sequence);
  375.   }
  376.  
  377.   __gnu_cxx::__mutex&
  378.   _Safe_iterator_base::
  379.   _M_get_mutex() throw ()
  380.   { return get_safe_base_mutex(_M_sequence); }
  381.  
  382.   _Safe_unordered_container_base*
  383.   _Safe_local_iterator_base::
  384.   _M_get_container() const _GLIBCXX_NOEXCEPT
  385.   { return static_cast<_Safe_unordered_container_base*>(_M_sequence); }
  386.  
  387.   void
  388.   _Safe_local_iterator_base::
  389.   _M_attach(_Safe_sequence_base* __cont, bool __constant)
  390.   {
  391.     _M_detach();
  392.    
  393.     // Attach to the new container (if there is one)
  394.     if (__cont)
  395.       {
  396.         _M_sequence = __cont;
  397.         _M_version = _M_sequence->_M_version;
  398.         _M_get_container()->_M_attach_local(this, __constant);
  399.       }
  400.   }
  401.  
  402.   void
  403.   _Safe_local_iterator_base::
  404.   _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw ()
  405.   {
  406.     _M_detach_single();
  407.    
  408.     // Attach to the new container (if there is one)
  409.     if (__cont)
  410.       {
  411.         _M_sequence = __cont;
  412.         _M_version = _M_sequence->_M_version;
  413.         _M_get_container()->_M_attach_local_single(this, __constant);
  414.       }
  415.   }
  416.  
  417.   void
  418.   _Safe_local_iterator_base::
  419.   _M_detach()
  420.   {
  421.     if (_M_sequence)
  422.       _M_get_container()->_M_detach_local(this);
  423.  
  424.     _M_reset();
  425.   }
  426.  
  427.   void
  428.   _Safe_local_iterator_base::
  429.   _M_detach_single() throw ()
  430.   {
  431.     if (_M_sequence)
  432.       _M_get_container()->_M_detach_local_single(this);
  433.  
  434.     _M_reset();
  435.   }
  436.  
  437.   void
  438.   _Safe_unordered_container_base::
  439.   _M_detach_all()
  440.   {
  441.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  442.     detach_all(_M_iterators);
  443.     _M_iterators = 0;
  444.    
  445.     detach_all(_M_const_iterators);
  446.     _M_const_iterators = 0;
  447.  
  448.     detach_all(_M_local_iterators);
  449.     _M_local_iterators = 0;
  450.  
  451.     detach_all(_M_const_local_iterators);
  452.     _M_const_local_iterators = 0;
  453.   }
  454.  
  455.   void
  456.   _Safe_unordered_container_base::
  457.   _M_swap(_Safe_unordered_container_base& __x)
  458.   {
  459.     // We need to lock both containers to swap
  460.     using namespace __gnu_cxx;
  461.     __mutex *__this_mutex = &_M_get_mutex();
  462.     __mutex *__x_mutex = &__x._M_get_mutex();
  463.     if (__this_mutex == __x_mutex)
  464.       {
  465.         __scoped_lock __lock(*__this_mutex);
  466.         swap_ucont(*this, __x);
  467.       }
  468.     else
  469.       {
  470.         __scoped_lock __l1(__this_mutex < __x_mutex
  471.                              ? *__this_mutex : *__x_mutex);
  472.         __scoped_lock __l2(__this_mutex < __x_mutex
  473.                              ? *__x_mutex : *__this_mutex);
  474.         swap_ucont(*this, __x);
  475.       }
  476.   }
  477.  
  478.   void
  479.   _Safe_unordered_container_base::
  480.   _M_attach_local(_Safe_iterator_base* __it, bool __constant)
  481.   {
  482.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  483.     _M_attach_local_single(__it, __constant);
  484.   }
  485.  
  486.   void
  487.   _Safe_unordered_container_base::
  488.   _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ()
  489.   {
  490.     _Safe_iterator_base*& __its =
  491.       __constant ? _M_const_local_iterators : _M_local_iterators;
  492.     __it->_M_next = __its;
  493.     if (__it->_M_next)
  494.       __it->_M_next->_M_prior = __it;
  495.     __its = __it;
  496.   }
  497.  
  498.   void
  499.   _Safe_unordered_container_base::
  500.   _M_detach_local(_Safe_iterator_base* __it)
  501.   {
  502.     // Remove __it from this container's list
  503.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  504.     _M_detach_local_single(__it);
  505.   }
  506.  
  507.   void
  508.   _Safe_unordered_container_base::
  509.   _M_detach_local_single(_Safe_iterator_base* __it) throw ()
  510.   {
  511.     // Remove __it from this container's list
  512.     __it->_M_unlink();
  513.     if (_M_const_local_iterators == __it)
  514.       _M_const_local_iterators = __it->_M_next;
  515.     if (_M_local_iterators == __it)
  516.       _M_local_iterators = __it->_M_next;
  517.   }
  518.  
  519.   void
  520.   _Error_formatter::_Parameter::
  521.   _M_print_field(const _Error_formatter* __formatter, const char* __name) const
  522.   {
  523.     assert(this->_M_kind != _Parameter::__unused_param);
  524.     const int __bufsize = 64;
  525.     char __buf[__bufsize];
  526.    
  527.     if (_M_kind == __iterator)
  528.       {
  529.         if (strcmp(__name, "name") == 0)
  530.           {
  531.             assert(_M_variant._M_iterator._M_name);
  532.             __formatter->_M_print_word(_M_variant._M_iterator._M_name);
  533.           }
  534.         else if (strcmp(__name, "address") == 0)
  535.           {
  536.             __formatter->_M_format_word(__buf, __bufsize, "%p",
  537.                                         _M_variant._M_iterator._M_address);
  538.             __formatter->_M_print_word(__buf);
  539.           }
  540.         else if (strcmp(__name, "type") == 0)
  541.           {
  542.             if (!_M_variant._M_iterator._M_type)
  543.               __formatter->_M_print_word("<unknown type>");
  544.             else
  545.               // TBD: demangle!
  546.               __formatter->_M_print_word(_M_variant._M_iterator.
  547.                                          _M_type->name());
  548.           }
  549.         else if (strcmp(__name, "constness") == 0)
  550.           {
  551.             static const char* __constness_names[__last_constness] =
  552.               {
  553.                 "<unknown>",
  554.                 "constant",
  555.                 "mutable"
  556.               };
  557.             __formatter->_M_print_word(__constness_names[_M_variant.
  558.                                                          _M_iterator.
  559.                                                          _M_constness]);
  560.           }
  561.         else if (strcmp(__name, "state") == 0)
  562.           {
  563.             static const char* __state_names[__last_state] =
  564.               {
  565.                 "<unknown>",
  566.                 "singular",
  567.                 "dereferenceable (start-of-sequence)",
  568.                 "dereferenceable",
  569.                 "past-the-end",
  570.                 "before-begin"
  571.               };
  572.             __formatter->_M_print_word(__state_names[_M_variant.
  573.                                                      _M_iterator._M_state]);
  574.           }
  575.         else if (strcmp(__name, "sequence") == 0)
  576.           {
  577.             assert(_M_variant._M_iterator._M_sequence);
  578.             __formatter->_M_format_word(__buf, __bufsize, "%p",
  579.                                         _M_variant._M_iterator._M_sequence);
  580.             __formatter->_M_print_word(__buf);
  581.           }
  582.         else if (strcmp(__name, "seq_type") == 0)
  583.           {
  584.             if (!_M_variant._M_iterator._M_seq_type)
  585.               __formatter->_M_print_word("<unknown seq_type>");
  586.             else
  587.               // TBD: demangle!
  588.               __formatter->_M_print_word(_M_variant._M_iterator.
  589.                                          _M_seq_type->name());
  590.           }
  591.         else
  592.           assert(false);
  593.       }
  594.     else if (_M_kind == __sequence)
  595.       {
  596.         if (strcmp(__name, "name") == 0)
  597.           {
  598.             assert(_M_variant._M_sequence._M_name);
  599.             __formatter->_M_print_word(_M_variant._M_sequence._M_name);
  600.           }
  601.         else if (strcmp(__name, "address") == 0)
  602.           {
  603.             assert(_M_variant._M_sequence._M_address);
  604.             __formatter->_M_format_word(__buf, __bufsize, "%p",
  605.                                         _M_variant._M_sequence._M_address);
  606.             __formatter->_M_print_word(__buf);
  607.           }
  608.         else if (strcmp(__name, "type") == 0)
  609.           {
  610.             if (!_M_variant._M_sequence._M_type)
  611.               __formatter->_M_print_word("<unknown type>");
  612.             else
  613.               // TBD: demangle!
  614.               __formatter->_M_print_word(_M_variant._M_sequence.
  615.                                          _M_type->name());
  616.           }
  617.         else
  618.           assert(false);
  619.       }
  620.     else if (_M_kind == __integer)
  621.       {
  622.         if (strcmp(__name, "name") == 0)
  623.           {
  624.             assert(_M_variant._M_integer._M_name);
  625.             __formatter->_M_print_word(_M_variant._M_integer._M_name);
  626.           }
  627.         else
  628.         assert(false);
  629.       }
  630.     else if (_M_kind == __string)
  631.       {
  632.         if (strcmp(__name, "name") == 0)
  633.           {
  634.             assert(_M_variant._M_string._M_name);
  635.             __formatter->_M_print_word(_M_variant._M_string._M_name);
  636.           }
  637.         else
  638.           assert(false);
  639.       }
  640.     else
  641.       {
  642.         assert(false);
  643.       }
  644.   }
  645.  
  646.   void
  647.   _Error_formatter::_Parameter::
  648.   _M_print_description(const _Error_formatter* __formatter) const
  649.   {
  650.     const int __bufsize = 128;
  651.     char __buf[__bufsize];
  652.    
  653.     if (_M_kind == __iterator)
  654.       {
  655.         __formatter->_M_print_word("iterator ");
  656.         if (_M_variant._M_iterator._M_name)
  657.           {
  658.             __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
  659.                                         _M_variant._M_iterator._M_name);
  660.             __formatter->_M_print_word(__buf);
  661.           }
  662.        
  663.         __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
  664.                                     _M_variant._M_iterator._M_address);
  665.         __formatter->_M_print_word(__buf);
  666.         if (_M_variant._M_iterator._M_type)
  667.           {
  668.             __formatter->_M_print_word("type = ");
  669.             _M_print_field(__formatter, "type");
  670.            
  671.             if (_M_variant._M_iterator._M_constness != __unknown_constness)
  672.               {
  673.                 __formatter->_M_print_word(" (");
  674.                 _M_print_field(__formatter, "constness");
  675.                 __formatter->_M_print_word(" iterator)");
  676.               }
  677.             __formatter->_M_print_word(";\n");
  678.           }
  679.        
  680.         if (_M_variant._M_iterator._M_state != __unknown_state)
  681.           {
  682.             __formatter->_M_print_word("  state = ");
  683.             _M_print_field(__formatter, "state");
  684.             __formatter->_M_print_word(";\n");
  685.           }
  686.        
  687.         if (_M_variant._M_iterator._M_sequence)
  688.           {
  689.             __formatter->_M_print_word("  references sequence ");
  690.             if (_M_variant._M_iterator._M_seq_type)
  691.               {
  692.                 __formatter->_M_print_word("with type `");
  693.                 _M_print_field(__formatter, "seq_type");
  694.                 __formatter->_M_print_word("' ");
  695.               }
  696.            
  697.             __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n",
  698.                                         _M_variant._M_sequence._M_address);
  699.             __formatter->_M_print_word(__buf);
  700.           }
  701.         __formatter->_M_print_word("}\n");
  702.       }
  703.     else if (_M_kind == __sequence)
  704.       {
  705.         __formatter->_M_print_word("sequence ");
  706.         if (_M_variant._M_sequence._M_name)
  707.           {
  708.             __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
  709.                                         _M_variant._M_sequence._M_name);
  710.             __formatter->_M_print_word(__buf);
  711.           }
  712.        
  713.         __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
  714.                                     _M_variant._M_sequence._M_address);
  715.         __formatter->_M_print_word(__buf);
  716.        
  717.         if (_M_variant._M_sequence._M_type)
  718.           {
  719.             __formatter->_M_print_word("  type = ");
  720.             _M_print_field(__formatter, "type");
  721.             __formatter->_M_print_word(";\n");
  722.           }      
  723.         __formatter->_M_print_word("}\n");
  724.       }
  725.   }
  726.  
  727.   const _Error_formatter&
  728.   _Error_formatter::_M_message(_Debug_msg_id __id) const throw ()
  729.   { return this->_M_message(_S_debug_messages[__id]); }
  730.  
  731.   void
  732.   _Error_formatter::_M_error() const
  733.   {
  734.     const int __bufsize = 128;
  735.     char __buf[__bufsize];
  736.    
  737.     // Emit file & line number information
  738.     _M_column = 1;
  739.     _M_wordwrap = false;
  740.     if (_M_file)
  741.       {
  742.         _M_format_word(__buf, __bufsize, "%s:", _M_file);
  743.         _M_print_word(__buf);
  744.         _M_column += strlen(__buf);
  745.       }
  746.    
  747.     if (_M_line > 0)
  748.       {
  749.         _M_format_word(__buf, __bufsize, "%u:", _M_line);
  750.         _M_print_word(__buf);
  751.         _M_column += strlen(__buf);
  752.       }
  753.    
  754.     if (_M_max_length)
  755.       _M_wordwrap = true;
  756.     _M_print_word("error: ");
  757.    
  758.     // Print the error message
  759.     assert(_M_text);
  760.     _M_print_string(_M_text);
  761.     _M_print_word(".\n");
  762.    
  763.     // Emit descriptions of the objects involved in the operation
  764.     _M_wordwrap = false;
  765.     bool __has_noninteger_parameters = false;
  766.     for (unsigned int __i = 0; __i < _M_num_parameters; ++__i)
  767.       {
  768.         if (_M_parameters[__i]._M_kind == _Parameter::__iterator
  769.             || _M_parameters[__i]._M_kind == _Parameter::__sequence)
  770.           {
  771.             if (!__has_noninteger_parameters)
  772.               {
  773.                 _M_first_line = true;
  774.                 _M_print_word("\nObjects involved in the operation:\n");
  775.                 __has_noninteger_parameters = true;
  776.               }
  777.             _M_parameters[__i]._M_print_description(this);
  778.           }
  779.       }
  780.    
  781.     abort();
  782.   }
  783.  
  784.   template<typename _Tp>
  785.     void
  786.     _Error_formatter::_M_format_word(char* __buf,
  787.                                      int __n __attribute__ ((__unused__)),
  788.                                      const char* __fmt, _Tp __s) const throw ()
  789.     {
  790. #ifdef _GLIBCXX_USE_C99
  791.       std::snprintf(__buf, __n, __fmt, __s);
  792. #else
  793.       std::sprintf(__buf, __fmt, __s);
  794. #endif
  795.     }
  796.  
  797.  
  798.   void
  799.   _Error_formatter::_M_print_word(const char* __word) const
  800.   {
  801.     if (!_M_wordwrap)
  802.       {
  803.         fprintf(stderr, "%s", __word);
  804.         return;
  805.       }
  806.    
  807.     size_t __length = strlen(__word);
  808.     if (__length == 0)
  809.       return;
  810.    
  811.     if ((_M_column + __length < _M_max_length)
  812.         || (__length >= _M_max_length && _M_column == 1))
  813.       {
  814.         // If this isn't the first line, indent
  815.         if (_M_column == 1 && !_M_first_line)
  816.           {
  817.             char __spacing[_M_indent + 1];
  818.             for (int i = 0; i < _M_indent; ++i)
  819.               __spacing[i] = ' ';
  820.             __spacing[_M_indent] = '\0';
  821.             fprintf(stderr, "%s", __spacing);
  822.             _M_column += _M_indent;
  823.           }
  824.        
  825.         fprintf(stderr, "%s", __word);
  826.         _M_column += __length;
  827.        
  828.         if (__word[__length - 1] == '\n')
  829.           {
  830.             _M_first_line = false;
  831.             _M_column = 1;
  832.           }
  833.       }
  834.     else
  835.       {
  836.         _M_column = 1;
  837.         _M_print_word("\n");
  838.         _M_print_word(__word);
  839.       }
  840.   }
  841.  
  842.   void
  843.   _Error_formatter::
  844.   _M_print_string(const char* __string) const
  845.   {
  846.     const char* __start = __string;
  847.     const char* __finish = __start;
  848.     const int __bufsize = 128;
  849.     char __buf[__bufsize];
  850.  
  851.     while (*__start)
  852.       {
  853.         if (*__start != '%')
  854.           {
  855.             // [__start, __finish) denotes the next word
  856.             __finish = __start;
  857.             while (isalnum(*__finish))
  858.               ++__finish;
  859.             if (__start == __finish)
  860.               ++__finish;
  861.             if (isspace(*__finish))
  862.               ++__finish;
  863.            
  864.             const ptrdiff_t __len = __finish - __start;
  865.             assert(__len < __bufsize);
  866.             memcpy(__buf, __start, __len);
  867.             __buf[__len] = '\0';
  868.             _M_print_word(__buf);
  869.             __start = __finish;
  870.            
  871.             // Skip extra whitespace
  872.             while (*__start == ' ')
  873.               ++__start;
  874.            
  875.             continue;
  876.           }
  877.        
  878.         ++__start;
  879.         assert(*__start);
  880.         if (*__start == '%')
  881.           {
  882.             _M_print_word("%");
  883.             ++__start;
  884.             continue;
  885.           }
  886.        
  887.         // Get the parameter number
  888.         assert(*__start >= '1' && *__start <= '9');
  889.         size_t __param = *__start - '0';
  890.         --__param;
  891.         assert(__param < _M_num_parameters);
  892.      
  893.         // '.' separates the parameter number from the field
  894.         // name, if there is one.
  895.         ++__start;
  896.         if (*__start != '.')
  897.           {
  898.             assert(*__start == ';');
  899.             ++__start;
  900.             __buf[0] = '\0';
  901.             if (_M_parameters[__param]._M_kind == _Parameter::__integer)
  902.               {
  903.                 _M_format_word(__buf, __bufsize, "%ld",
  904.                                _M_parameters[__param]._M_variant._M_integer._M_value);
  905.                 _M_print_word(__buf);
  906.               }
  907.             else if (_M_parameters[__param]._M_kind == _Parameter::__string)
  908.               _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value);
  909.             continue;
  910.           }
  911.        
  912.         // Extract the field name we want
  913.         enum { __max_field_len = 16 };
  914.         char __field[__max_field_len];
  915.         int __field_idx = 0;
  916.         ++__start;
  917.         while (*__start != ';')
  918.           {
  919.             assert(*__start);
  920.             assert(__field_idx < __max_field_len-1);
  921.             __field[__field_idx++] = *__start++;
  922.           }
  923.         ++__start;
  924.         __field[__field_idx] = 0;
  925.        
  926.         _M_parameters[__param]._M_print_field(this, __field);            
  927.       }
  928.   }
  929.  
  930.   void
  931.   _Error_formatter::_M_get_max_length() const throw ()
  932.   {
  933.     const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
  934.     if (__nptr)
  935.       {
  936.         char* __endptr;
  937.         const unsigned long __ret = std::strtoul(__nptr, &__endptr, 0);
  938.         if (*__nptr != '\0' && *__endptr == '\0')
  939.           _M_max_length = __ret;
  940.       }
  941.   }
  942.  
  943.   // Instantiations.
  944.   template
  945.     void
  946.     _Error_formatter::_M_format_word(char*, int, const char*,
  947.                                      const void*) const;
  948.  
  949.   template
  950.     void
  951.     _Error_formatter::_M_format_word(char*, int, const char*, long) const;
  952.  
  953.   template
  954.     void
  955.     _Error_formatter::_M_format_word(char*, int, const char*,
  956.                                      std::size_t) const;
  957.  
  958.   template
  959.     void
  960.     _Error_formatter::_M_format_word(char*, int, const char*,
  961.                                      const char*) const;
  962. } // namespace __gnu_debug
  963.