Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6554 serge 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
// .
25
 
26
#include 
27
#include 
28
#include 
29
 
30
namespace std {
31
_GLIBCXX_BEGIN_NAMESPACE_VERSION
32
  template
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(__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(__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