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