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