Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Debugging mode support code -*- C++ -*-
  2.  
  3. // Copyright (C) 2003-2015 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_base.h>
  27. #include <debug/safe_unordered_base.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.     "attempt to insert with an iterator range [%1.name;, %2.name;) from this container"
  186.   };
  187.  
  188.   void
  189.   _Safe_sequence_base::
  190.   _M_detach_all()
  191.   {
  192.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  193.     detach_all(_M_iterators);
  194.     _M_iterators = 0;
  195.    
  196.     detach_all(_M_const_iterators);
  197.     _M_const_iterators = 0;
  198.   }
  199.  
  200.   void
  201.   _Safe_sequence_base::
  202.   _M_detach_singular()
  203.   {
  204.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  205.     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
  206.       {
  207.         _Safe_iterator_base* __old = __iter;
  208.         __iter = __iter->_M_next;
  209.         if (__old->_M_singular())
  210.           __old->_M_detach_single();
  211.       }
  212.  
  213.     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
  214.       {
  215.         _Safe_iterator_base* __old = __iter2;
  216.         __iter2 = __iter2->_M_next;
  217.         if (__old->_M_singular())
  218.           __old->_M_detach_single();
  219.       }
  220.   }
  221.  
  222.   void
  223.   _Safe_sequence_base::
  224.   _M_revalidate_singular()
  225.   {
  226.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  227.     for (_Safe_iterator_base* __iter = _M_iterators; __iter;
  228.          __iter = __iter->_M_next)
  229.       __iter->_M_version = _M_version;
  230.  
  231.     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
  232.          __iter2 = __iter2->_M_next)
  233.       __iter2->_M_version = _M_version;
  234.   }
  235.  
  236.   void
  237.   _Safe_sequence_base::
  238.   _M_swap(_Safe_sequence_base& __x) noexcept
  239.   {
  240.     // We need to lock both sequences to swap
  241.     using namespace __gnu_cxx;
  242.     __mutex *__this_mutex = &_M_get_mutex();
  243.     __mutex *__x_mutex = &__x._M_get_mutex();
  244.     if (__this_mutex == __x_mutex)
  245.       {
  246.         __scoped_lock __lock(*__this_mutex);
  247.         swap_seq(*this, __x);
  248.       }
  249.     else
  250.       {
  251.         __scoped_lock __l1(__this_mutex < __x_mutex
  252.                              ? *__this_mutex : *__x_mutex);
  253.         __scoped_lock __l2(__this_mutex < __x_mutex
  254.                              ? *__x_mutex : *__this_mutex);
  255.         swap_seq(*this, __x);
  256.       }
  257.   }
  258.  
  259.   __gnu_cxx::__mutex&
  260.   _Safe_sequence_base::
  261.   _M_get_mutex() throw ()
  262.   { return get_safe_base_mutex(this); }
  263.  
  264.   void
  265.   _Safe_sequence_base::
  266.   _M_attach(_Safe_iterator_base* __it, bool __constant)
  267.   {
  268.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  269.     _M_attach_single(__it, __constant);
  270.   }
  271.  
  272.   void
  273.   _Safe_sequence_base::
  274.   _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ()
  275.   {
  276.     _Safe_iterator_base*& __its =
  277.       __constant ? _M_const_iterators : _M_iterators;
  278.     __it->_M_next = __its;
  279.     if (__it->_M_next)
  280.       __it->_M_next->_M_prior = __it;
  281.     __its = __it;
  282.   }
  283.  
  284.   void
  285.   _Safe_sequence_base::
  286.   _M_detach(_Safe_iterator_base* __it)
  287.   {
  288.     // Remove __it from this sequence's list
  289.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  290.     _M_detach_single(__it);
  291.   }
  292.  
  293.   void
  294.   _Safe_sequence_base::
  295.   _M_detach_single(_Safe_iterator_base* __it) throw ()
  296.   {
  297.     // Remove __it from this sequence's list
  298.     __it->_M_unlink();
  299.     if (_M_const_iterators == __it)
  300.       _M_const_iterators = __it->_M_next;
  301.     if (_M_iterators == __it)
  302.       _M_iterators = __it->_M_next;
  303.   }
  304.  
  305.   void
  306.   _Safe_iterator_base::
  307.   _M_attach(_Safe_sequence_base* __seq, bool __constant)
  308.   {
  309.     _M_detach();
  310.    
  311.     // Attach to the new sequence (if there is one)
  312.     if (__seq)
  313.       {
  314.         _M_sequence = __seq;
  315.         _M_version = _M_sequence->_M_version;
  316.         _M_sequence->_M_attach(this, __constant);
  317.       }
  318.   }
  319.  
  320.   void
  321.   _Safe_iterator_base::
  322.   _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ()
  323.   {
  324.     _M_detach_single();
  325.    
  326.     // Attach to the new sequence (if there is one)
  327.     if (__seq)
  328.       {
  329.         _M_sequence = __seq;
  330.         _M_version = _M_sequence->_M_version;
  331.         _M_sequence->_M_attach_single(this, __constant);
  332.       }
  333.   }
  334.  
  335.   void
  336.   _Safe_iterator_base::
  337.   _M_detach()
  338.   {
  339.     if (_M_sequence)
  340.       _M_sequence->_M_detach(this);
  341.  
  342.     _M_reset();
  343.   }
  344.  
  345.   void
  346.   _Safe_iterator_base::
  347.   _M_detach_single() throw ()
  348.   {
  349.     if (_M_sequence)
  350.       _M_sequence->_M_detach_single(this);
  351.  
  352.     _M_reset();
  353.   }
  354.  
  355.   void
  356.   _Safe_iterator_base::
  357.   _M_reset() throw ()
  358.   {
  359.     _M_sequence = 0;
  360.     _M_version = 0;
  361.     _M_prior = 0;
  362.     _M_next = 0;
  363.   }
  364.  
  365.   bool
  366.   _Safe_iterator_base::
  367.   _M_singular() const throw ()
  368.   { return !_M_sequence || _M_version != _M_sequence->_M_version; }
  369.    
  370.   bool
  371.   _Safe_iterator_base::
  372.   _M_can_compare(const _Safe_iterator_base& __x) const throw ()
  373.   {
  374.     return (!_M_singular()
  375.             && !__x._M_singular() && _M_sequence == __x._M_sequence);
  376.   }
  377.  
  378.   __gnu_cxx::__mutex&
  379.   _Safe_iterator_base::
  380.   _M_get_mutex() throw ()
  381.   { return get_safe_base_mutex(_M_sequence); }
  382.  
  383.   _Safe_unordered_container_base*
  384.   _Safe_local_iterator_base::
  385.   _M_get_container() const noexcept
  386.   { return static_cast<_Safe_unordered_container_base*>(_M_sequence); }
  387.  
  388.   void
  389.   _Safe_local_iterator_base::
  390.   _M_attach(_Safe_sequence_base* __cont, bool __constant)
  391.   {
  392.     _M_detach();
  393.    
  394.     // Attach to the new container (if there is one)
  395.     if (__cont)
  396.       {
  397.         _M_sequence = __cont;
  398.         _M_version = _M_sequence->_M_version;
  399.         _M_get_container()->_M_attach_local(this, __constant);
  400.       }
  401.   }
  402.  
  403.   void
  404.   _Safe_local_iterator_base::
  405.   _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw ()
  406.   {
  407.     _M_detach_single();
  408.    
  409.     // Attach to the new container (if there is one)
  410.     if (__cont)
  411.       {
  412.         _M_sequence = __cont;
  413.         _M_version = _M_sequence->_M_version;
  414.         _M_get_container()->_M_attach_local_single(this, __constant);
  415.       }
  416.   }
  417.  
  418.   void
  419.   _Safe_local_iterator_base::
  420.   _M_detach()
  421.   {
  422.     if (_M_sequence)
  423.       _M_get_container()->_M_detach_local(this);
  424.  
  425.     _M_reset();
  426.   }
  427.  
  428.   void
  429.   _Safe_local_iterator_base::
  430.   _M_detach_single() throw ()
  431.   {
  432.     if (_M_sequence)
  433.       _M_get_container()->_M_detach_local_single(this);
  434.  
  435.     _M_reset();
  436.   }
  437.  
  438.   void
  439.   _Safe_unordered_container_base::
  440.   _M_detach_all()
  441.   {
  442.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  443.     detach_all(_M_iterators);
  444.     _M_iterators = 0;
  445.    
  446.     detach_all(_M_const_iterators);
  447.     _M_const_iterators = 0;
  448.  
  449.     detach_all(_M_local_iterators);
  450.     _M_local_iterators = 0;
  451.  
  452.     detach_all(_M_const_local_iterators);
  453.     _M_const_local_iterators = 0;
  454.   }
  455.  
  456.   void
  457.   _Safe_unordered_container_base::
  458.   _M_swap(_Safe_unordered_container_base& __x) noexcept
  459.   {
  460.     // We need to lock both containers to swap
  461.     using namespace __gnu_cxx;
  462.     __mutex *__this_mutex = &_M_get_mutex();
  463.     __mutex *__x_mutex = &__x._M_get_mutex();
  464.     if (__this_mutex == __x_mutex)
  465.       {
  466.         __scoped_lock __lock(*__this_mutex);
  467.         swap_ucont(*this, __x);
  468.       }
  469.     else
  470.       {
  471.         __scoped_lock __l1(__this_mutex < __x_mutex
  472.                              ? *__this_mutex : *__x_mutex);
  473.         __scoped_lock __l2(__this_mutex < __x_mutex
  474.                              ? *__x_mutex : *__this_mutex);
  475.         swap_ucont(*this, __x);
  476.       }
  477.   }
  478.  
  479.   void
  480.   _Safe_unordered_container_base::
  481.   _M_attach_local(_Safe_iterator_base* __it, bool __constant)
  482.   {
  483.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  484.     _M_attach_local_single(__it, __constant);
  485.   }
  486.  
  487.   void
  488.   _Safe_unordered_container_base::
  489.   _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ()
  490.   {
  491.     _Safe_iterator_base*& __its =
  492.       __constant ? _M_const_local_iterators : _M_local_iterators;
  493.     __it->_M_next = __its;
  494.     if (__it->_M_next)
  495.       __it->_M_next->_M_prior = __it;
  496.     __its = __it;
  497.   }
  498.  
  499.   void
  500.   _Safe_unordered_container_base::
  501.   _M_detach_local(_Safe_iterator_base* __it)
  502.   {
  503.     // Remove __it from this container's list
  504.     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
  505.     _M_detach_local_single(__it);
  506.   }
  507.  
  508.   void
  509.   _Safe_unordered_container_base::
  510.   _M_detach_local_single(_Safe_iterator_base* __it) throw ()
  511.   {
  512.     // Remove __it from this container's list
  513.     __it->_M_unlink();
  514.     if (_M_const_local_iterators == __it)
  515.       _M_const_local_iterators = __it->_M_next;
  516.     if (_M_local_iterators == __it)
  517.       _M_local_iterators = __it->_M_next;
  518.   }
  519.  
  520.   void
  521.   _Error_formatter::_Parameter::
  522.   _M_print_field(const _Error_formatter* __formatter, const char* __name) const
  523.   {
  524.     assert(this->_M_kind != _Parameter::__unused_param);
  525.     const int __bufsize = 64;
  526.     char __buf[__bufsize];
  527.    
  528.     if (_M_kind == __iterator)
  529.       {
  530.         if (strcmp(__name, "name") == 0)
  531.           {
  532.             assert(_M_variant._M_iterator._M_name);
  533.             __formatter->_M_print_word(_M_variant._M_iterator._M_name);
  534.           }
  535.         else if (strcmp(__name, "address") == 0)
  536.           {
  537.             __formatter->_M_format_word(__buf, __bufsize, "%p",
  538.                                         _M_variant._M_iterator._M_address);
  539.             __formatter->_M_print_word(__buf);
  540.           }
  541.         else if (strcmp(__name, "type") == 0)
  542.           {
  543.             if (!_M_variant._M_iterator._M_type)
  544.               __formatter->_M_print_word("<unknown type>");
  545.             else
  546.               // TBD: demangle!
  547.               __formatter->_M_print_word(_M_variant._M_iterator.
  548.                                          _M_type->name());
  549.           }
  550.         else if (strcmp(__name, "constness") == 0)
  551.           {
  552.             static const char* __constness_names[__last_constness] =
  553.               {
  554.                 "<unknown>",
  555.                 "constant",
  556.                 "mutable"
  557.               };
  558.             __formatter->_M_print_word(__constness_names[_M_variant.
  559.                                                          _M_iterator.
  560.                                                          _M_constness]);
  561.           }
  562.         else if (strcmp(__name, "state") == 0)
  563.           {
  564.             static const char* __state_names[__last_state] =
  565.               {
  566.                 "<unknown>",
  567.                 "singular",
  568.                 "dereferenceable (start-of-sequence)",
  569.                 "dereferenceable",
  570.                 "past-the-end",
  571.                 "before-begin"
  572.               };
  573.             __formatter->_M_print_word(__state_names[_M_variant.
  574.                                                      _M_iterator._M_state]);
  575.           }
  576.         else if (strcmp(__name, "sequence") == 0)
  577.           {
  578.             assert(_M_variant._M_iterator._M_sequence);
  579.             __formatter->_M_format_word(__buf, __bufsize, "%p",
  580.                                         _M_variant._M_iterator._M_sequence);
  581.             __formatter->_M_print_word(__buf);
  582.           }
  583.         else if (strcmp(__name, "seq_type") == 0)
  584.           {
  585.             if (!_M_variant._M_iterator._M_seq_type)
  586.               __formatter->_M_print_word("<unknown seq_type>");
  587.             else
  588.               // TBD: demangle!
  589.               __formatter->_M_print_word(_M_variant._M_iterator.
  590.                                          _M_seq_type->name());
  591.           }
  592.         else
  593.           assert(false);
  594.       }
  595.     else if (_M_kind == __sequence)
  596.       {
  597.         if (strcmp(__name, "name") == 0)
  598.           {
  599.             assert(_M_variant._M_sequence._M_name);
  600.             __formatter->_M_print_word(_M_variant._M_sequence._M_name);
  601.           }
  602.         else if (strcmp(__name, "address") == 0)
  603.           {
  604.             assert(_M_variant._M_sequence._M_address);
  605.             __formatter->_M_format_word(__buf, __bufsize, "%p",
  606.                                         _M_variant._M_sequence._M_address);
  607.             __formatter->_M_print_word(__buf);
  608.           }
  609.         else if (strcmp(__name, "type") == 0)
  610.           {
  611.             if (!_M_variant._M_sequence._M_type)
  612.               __formatter->_M_print_word("<unknown type>");
  613.             else
  614.               // TBD: demangle!
  615.               __formatter->_M_print_word(_M_variant._M_sequence.
  616.                                          _M_type->name());
  617.           }
  618.         else
  619.           assert(false);
  620.       }
  621.     else if (_M_kind == __integer)
  622.       {
  623.         if (strcmp(__name, "name") == 0)
  624.           {
  625.             assert(_M_variant._M_integer._M_name);
  626.             __formatter->_M_print_word(_M_variant._M_integer._M_name);
  627.           }
  628.         else
  629.         assert(false);
  630.       }
  631.     else if (_M_kind == __string)
  632.       {
  633.         if (strcmp(__name, "name") == 0)
  634.           {
  635.             assert(_M_variant._M_string._M_name);
  636.             __formatter->_M_print_word(_M_variant._M_string._M_name);
  637.           }
  638.         else
  639.           assert(false);
  640.       }
  641.     else
  642.       {
  643.         assert(false);
  644.       }
  645.   }
  646.  
  647.   void
  648.   _Error_formatter::_Parameter::
  649.   _M_print_description(const _Error_formatter* __formatter) const
  650.   {
  651.     const int __bufsize = 128;
  652.     char __buf[__bufsize];
  653.    
  654.     if (_M_kind == __iterator)
  655.       {
  656.         __formatter->_M_print_word("iterator ");
  657.         if (_M_variant._M_iterator._M_name)
  658.           {
  659.             __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
  660.                                         _M_variant._M_iterator._M_name);
  661.             __formatter->_M_print_word(__buf);
  662.           }
  663.        
  664.         __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
  665.                                     _M_variant._M_iterator._M_address);
  666.         __formatter->_M_print_word(__buf);
  667.         if (_M_variant._M_iterator._M_type)
  668.           {
  669.             __formatter->_M_print_word("type = ");
  670.             _M_print_field(__formatter, "type");
  671.            
  672.             if (_M_variant._M_iterator._M_constness != __unknown_constness)
  673.               {
  674.                 __formatter->_M_print_word(" (");
  675.                 _M_print_field(__formatter, "constness");
  676.                 __formatter->_M_print_word(" iterator)");
  677.               }
  678.             __formatter->_M_print_word(";\n");
  679.           }
  680.        
  681.         if (_M_variant._M_iterator._M_state != __unknown_state)
  682.           {
  683.             __formatter->_M_print_word("  state = ");
  684.             _M_print_field(__formatter, "state");
  685.             __formatter->_M_print_word(";\n");
  686.           }
  687.        
  688.         if (_M_variant._M_iterator._M_sequence)
  689.           {
  690.             __formatter->_M_print_word("  references sequence ");
  691.             if (_M_variant._M_iterator._M_seq_type)
  692.               {
  693.                 __formatter->_M_print_word("with type `");
  694.                 _M_print_field(__formatter, "seq_type");
  695.                 __formatter->_M_print_word("' ");
  696.               }
  697.            
  698.             __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n",
  699.                                         _M_variant._M_iterator._M_sequence);
  700.             __formatter->_M_print_word(__buf);
  701.           }
  702.         __formatter->_M_print_word("}\n");
  703.       }
  704.     else if (_M_kind == __sequence)
  705.       {
  706.         __formatter->_M_print_word("sequence ");
  707.         if (_M_variant._M_sequence._M_name)
  708.           {
  709.             __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
  710.                                         _M_variant._M_sequence._M_name);
  711.             __formatter->_M_print_word(__buf);
  712.           }
  713.        
  714.         __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
  715.                                     _M_variant._M_sequence._M_address);
  716.         __formatter->_M_print_word(__buf);
  717.        
  718.         if (_M_variant._M_sequence._M_type)
  719.           {
  720.             __formatter->_M_print_word("  type = ");
  721.             _M_print_field(__formatter, "type");
  722.             __formatter->_M_print_word(";\n");
  723.           }      
  724.         __formatter->_M_print_word("}\n");
  725.       }
  726.   }
  727.  
  728.   const _Error_formatter&
  729.   _Error_formatter::_M_message(_Debug_msg_id __id) const throw ()
  730.   { return this->_M_message(_S_debug_messages[__id]); }
  731.  
  732.   void
  733.   _Error_formatter::_M_error() const
  734.   {
  735.     const int __bufsize = 128;
  736.     char __buf[__bufsize];
  737.    
  738.     // Emit file & line number information
  739.     _M_column = 1;
  740.     _M_wordwrap = false;
  741.     if (_M_file)
  742.       {
  743.         _M_format_word(__buf, __bufsize, "%s:", _M_file);
  744.         _M_print_word(__buf);
  745.         _M_column += strlen(__buf);
  746.       }
  747.    
  748.     if (_M_line > 0)
  749.       {
  750.         _M_format_word(__buf, __bufsize, "%u:", _M_line);
  751.         _M_print_word(__buf);
  752.         _M_column += strlen(__buf);
  753.       }
  754.    
  755.     if (_M_max_length)
  756.       _M_wordwrap = true;
  757.     _M_print_word("error: ");
  758.    
  759.     // Print the error message
  760.     assert(_M_text);
  761.     _M_print_string(_M_text);
  762.     _M_print_word(".\n");
  763.    
  764.     // Emit descriptions of the objects involved in the operation
  765.     _M_wordwrap = false;
  766.     bool __has_noninteger_parameters = false;
  767.     for (unsigned int __i = 0; __i < _M_num_parameters; ++__i)
  768.       {
  769.         if (_M_parameters[__i]._M_kind == _Parameter::__iterator
  770.             || _M_parameters[__i]._M_kind == _Parameter::__sequence)
  771.           {
  772.             if (!__has_noninteger_parameters)
  773.               {
  774.                 _M_first_line = true;
  775.                 _M_print_word("\nObjects involved in the operation:\n");
  776.                 __has_noninteger_parameters = true;
  777.               }
  778.             _M_parameters[__i]._M_print_description(this);
  779.           }
  780.       }
  781.    
  782.     abort();
  783.   }
  784.  
  785.   template<typename _Tp>
  786.     void
  787.     _Error_formatter::_M_format_word(char* __buf,
  788.                                      int __n __attribute__ ((__unused__)),
  789.                                      const char* __fmt, _Tp __s) const throw ()
  790.     {
  791. #ifdef _GLIBCXX_USE_C99
  792.       std::snprintf(__buf, __n, __fmt, __s);
  793. #else
  794.       std::sprintf(__buf, __fmt, __s);
  795. #endif
  796.     }
  797.  
  798.  
  799.   void
  800.   _Error_formatter::_M_print_word(const char* __word) const
  801.   {
  802.     if (!_M_wordwrap)
  803.       {
  804.         fprintf(stderr, "%s", __word);
  805.         return;
  806.       }
  807.    
  808.     size_t __length = strlen(__word);
  809.     if (__length == 0)
  810.       return;
  811.    
  812.     size_t __visual_length
  813.       = __word[__length - 1] == '\n' ? __length - 1 : __length;
  814.     if (__visual_length == 0
  815.         || (_M_column + __visual_length < _M_max_length)
  816.         || (__visual_length >= _M_max_length && _M_column == 1))
  817.       {
  818.         // If this isn't the first line, indent
  819.         if (_M_column == 1 && !_M_first_line)
  820.           {
  821.             char __spacing[_M_indent + 1];
  822.             for (int i = 0; i < _M_indent; ++i)
  823.               __spacing[i] = ' ';
  824.             __spacing[_M_indent] = '\0';
  825.             fprintf(stderr, "%s", __spacing);
  826.             _M_column += _M_indent;
  827.           }
  828.        
  829.         fprintf(stderr, "%s", __word);
  830.        
  831.         if (__word[__length - 1] == '\n')
  832.           {
  833.             _M_first_line = false;
  834.             _M_column = 1;
  835.           }
  836.         else
  837.           _M_column += __length;
  838.       }
  839.     else
  840.       {
  841.         _M_print_word("\n");
  842.         _M_print_word(__word);
  843.       }
  844.   }
  845.  
  846.   void
  847.   _Error_formatter::
  848.   _M_print_string(const char* __string) const
  849.   {
  850.     const char* __start = __string;
  851.     const char* __finish = __start;
  852.     const int __bufsize = 128;
  853.     char __buf[__bufsize];
  854.  
  855.     while (*__start)
  856.       {
  857.         if (*__start != '%')
  858.           {
  859.             // [__start, __finish) denotes the next word
  860.             __finish = __start;
  861.             while (isalnum(*__finish))
  862.               ++__finish;
  863.             if (__start == __finish)
  864.               ++__finish;
  865.             if (isspace(*__finish))
  866.               ++__finish;
  867.            
  868.             const ptrdiff_t __len = __finish - __start;
  869.             assert(__len < __bufsize);
  870.             memcpy(__buf, __start, __len);
  871.             __buf[__len] = '\0';
  872.             _M_print_word(__buf);
  873.             __start = __finish;
  874.            
  875.             // Skip extra whitespace
  876.             while (*__start == ' ')
  877.               ++__start;
  878.            
  879.             continue;
  880.           }
  881.        
  882.         ++__start;
  883.         assert(*__start);
  884.         if (*__start == '%')
  885.           {
  886.             _M_print_word("%");
  887.             ++__start;
  888.             continue;
  889.           }
  890.        
  891.         // Get the parameter number
  892.         assert(*__start >= '1' && *__start <= '9');
  893.         size_t __param = *__start - '0';
  894.         --__param;
  895.         assert(__param < _M_num_parameters);
  896.      
  897.         // '.' separates the parameter number from the field
  898.         // name, if there is one.
  899.         ++__start;
  900.         if (*__start != '.')
  901.           {
  902.             assert(*__start == ';');
  903.             ++__start;
  904.             __buf[0] = '\0';
  905.             if (_M_parameters[__param]._M_kind == _Parameter::__integer)
  906.               {
  907.                 _M_format_word(__buf, __bufsize, "%ld",
  908.                                _M_parameters[__param]._M_variant._M_integer._M_value);
  909.                 _M_print_word(__buf);
  910.               }
  911.             else if (_M_parameters[__param]._M_kind == _Parameter::__string)
  912.               _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value);
  913.             continue;
  914.           }
  915.        
  916.         // Extract the field name we want
  917.         enum { __max_field_len = 16 };
  918.         char __field[__max_field_len];
  919.         int __field_idx = 0;
  920.         ++__start;
  921.         while (*__start != ';')
  922.           {
  923.             assert(*__start);
  924.             assert(__field_idx < __max_field_len-1);
  925.             __field[__field_idx++] = *__start++;
  926.           }
  927.         ++__start;
  928.         __field[__field_idx] = 0;
  929.        
  930.         _M_parameters[__param]._M_print_field(this, __field);            
  931.       }
  932.   }
  933.  
  934.   void
  935.   _Error_formatter::_M_get_max_length() const throw ()
  936.   {
  937.     const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
  938.     if (__nptr)
  939.       {
  940.         char* __endptr;
  941.         const unsigned long __ret = std::strtoul(__nptr, &__endptr, 0);
  942.         if (*__nptr != '\0' && *__endptr == '\0')
  943.           _M_max_length = __ret;
  944.       }
  945.   }
  946.  
  947.   // Instantiations.
  948.   template
  949.     void
  950.     _Error_formatter::_M_format_word(char*, int, const char*,
  951.                                      const void*) const;
  952.  
  953.   template
  954.     void
  955.     _Error_formatter::_M_format_word(char*, int, const char*, long) const;
  956.  
  957.   template
  958.     void
  959.     _Error_formatter::_M_format_word(char*, int, const char*,
  960.                                      std::size_t) const;
  961.  
  962.   template
  963.     void
  964.     _Error_formatter::_M_format_word(char*, int, const char*,
  965.                                      const char*) const;
  966. } // namespace __gnu_debug
  967.