Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Debugging support -*- C++ -*-
  2.  
  3. // Copyright (C) 2013-2015 Free Software Foundation, Inc.
  4. //
  5. // This file is part of GCC.
  6. //
  7. // GCC is free software; you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License as published by
  9. // the Free Software Foundation; either version 3, or (at your option)
  10. // any later version.
  11. //
  12. // GCC 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. // Under Section 7 of GPL version 3, you are granted additional
  18. // permissions described in the GCC Runtime Library Exception, version
  19. // 3.1, as published by the Free Software Foundation.
  20.  
  21. // You should have received a copy of the GNU General Public License and
  22. // a copy of the GCC Runtime Library Exception along with this program;
  23. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  24. // <http://www.gnu.org/licenses/>.
  25.  
  26. #include <stdarg.h>
  27. #include <bits/functexcept.h>
  28. #include <bits/locale_facets.h>
  29.  
  30. namespace std {
  31. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  32.   template<typename _CharT, typename _ValueT>
  33.   int
  34.   __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
  35.                 ios_base::fmtflags __flags, bool __dec);
  36. _GLIBCXX_END_NAMESPACE_VERSION
  37. }
  38.  
  39. namespace __gnu_cxx {
  40.  
  41.   // Private helper to throw logic error if snprintf_lite runs out
  42.   // of space (which is not expected to ever happen).
  43.   // NUL-terminates __buf.
  44.   void
  45.   __throw_insufficient_space(const char *__buf, const char *__bufend)
  46.     __attribute__((__noreturn__));
  47.  
  48.   void
  49.   __throw_insufficient_space(const char *__buf, const char *__bufend)
  50.   {
  51.     // Include space for trailing NUL.
  52.     const size_t __len = __bufend - __buf + 1;
  53.  
  54.     const char __err[] = "not enough space for format expansion "
  55.       "(Please submit full bug report at http://gcc.gnu.org/bugs.html):\n    ";
  56.     const size_t __errlen = sizeof(__err) - 1;
  57.  
  58.     char *const __e
  59.       = static_cast<char*>(__builtin_alloca(__errlen + __len));
  60.  
  61.     __builtin_memcpy(__e, __err, __errlen);
  62.     __builtin_memcpy(__e + __errlen, __buf, __len - 1);
  63.     __e[__errlen + __len - 1] = '\0';
  64.     std::__throw_logic_error(__e);
  65.   }
  66.  
  67.  
  68.   // Private routine to append decimal representation of VAL to the given
  69.   // BUFFER, but not more than BUFSIZE characters.
  70.   // Does not NUL-terminate the output buffer.
  71.   // Returns number of characters appended, or -1 if BUFSIZE is too small.
  72.   int __concat_size_t(char *__buf, size_t __bufsize, size_t __val)
  73.   {
  74.     // __int_to_char is explicitly instantiated and available only for
  75.     // some, but not all, types. See locale-inst.cc.
  76. #ifdef _GLIBCXX_USE_LONG_LONG
  77.     unsigned long long __val2 = __val;
  78. #else
  79.     unsigned long __val2 = __val;
  80. #endif
  81.     // Long enough for decimal representation.
  82.     int __ilen = 3 * sizeof(__val2);
  83.     char *__cs = static_cast<char*>(__builtin_alloca(__ilen));
  84.     size_t __len = std::__int_to_char(__cs + __ilen, __val2,
  85.                                       std::__num_base::_S_atoms_out,
  86.                                       std::ios_base::dec, true);
  87.     if (__bufsize < __len)
  88.       return -1;
  89.  
  90.     __builtin_memcpy(__buf, __cs + __ilen - __len, __len);
  91.     return __len;
  92.   }
  93.  
  94.  
  95.   // Private routine to print into __buf arguments according to format,
  96.   // not to exceed __bufsize.
  97.   // Only '%%', '%s' and '%zu' format specifiers are understood.
  98.   // Returns number of characters printed (excluding terminating NUL).
  99.   // Always NUL-terminates __buf.
  100.   // Throws logic_error on insufficient space.
  101.   int __snprintf_lite(char *__buf, size_t __bufsize, const char *__fmt,
  102.                       va_list __ap)
  103.   {
  104.     char *__d = __buf;
  105.     const char *__s = __fmt;
  106.     const char *const __limit = __d + __bufsize - 1;  // Leave space for NUL.
  107.  
  108.     while (__s[0] != '\0' && __d < __limit)
  109.       {
  110.         if (__s[0] == '%')
  111.           switch (__s[1])
  112.             {
  113.             default:  // Stray '%'. Just print it.
  114.               break;
  115.             case '%':  // '%%'
  116.               __s += 1;
  117.               break;
  118.             case 's':  // '%s'.
  119.               {
  120.                 const char *__v = va_arg(__ap, const char *);
  121.  
  122.                 while (__v[0] != '\0' && __d < __limit)
  123.                   *__d++ = *__v++;
  124.  
  125.                 if (__v[0] != '\0')
  126.                   // Not enough space for __fmt expansion.
  127.                   __throw_insufficient_space(__buf, __d);
  128.  
  129.                 __s += 2;  // Step over %s.
  130.                 continue;
  131.               }
  132.               break;
  133.             case 'z':
  134.               if (__s[2] == 'u')  // '%zu' -- expand next size_t arg.
  135.                 {
  136.                   const int __len = __concat_size_t(__d, __limit - __d,
  137.                                                     va_arg(__ap, size_t));
  138.                   if (__len > 0)
  139.                     __d += __len;
  140.                   else
  141.                     // Not enough space for __fmt expansion.
  142.                     __throw_insufficient_space(__buf, __d);
  143.  
  144.                   __s += 3;  // Step over %zu
  145.                   continue;
  146.                 }
  147.               // Stray '%zX'. Just print it.
  148.               break;
  149.             }
  150.         *__d++ = *__s++;
  151.       }
  152.  
  153.     if (__s[0] != '\0')
  154.       // Not enough space for __fmt expansion.
  155.       __throw_insufficient_space(__buf, __d);
  156.  
  157.     *__d = '\0';
  158.     return __d - __buf;
  159.   }
  160.  
  161. }  // __gnu_cxx
  162.