Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/c++/src/system_error.cpp
12346 views
1
//===---------------------- system_error.cpp ------------------------------===//
2
//
3
// The LLVM Compiler Infrastructure
4
//
5
// This file is dual licensed under the MIT and the University of Illinois Open
6
// Source Licenses. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#include "__config"
11
12
#include "system_error"
13
14
#include "include/config_elast.h"
15
#include "cerrno"
16
#include "cstring"
17
#include "cstdio"
18
#include "cstdlib"
19
#include "string"
20
#include "string.h"
21
#include "__debug"
22
23
#if defined(__ANDROID__)
24
#include <android/api-level.h>
25
#endif
26
27
_LIBCPP_BEGIN_NAMESPACE_STD
28
29
// class error_category
30
31
#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
32
error_category::error_category() _NOEXCEPT
33
{
34
}
35
#endif
36
37
error_category::~error_category() _NOEXCEPT
38
{
39
}
40
41
error_condition
42
error_category::default_error_condition(int ev) const _NOEXCEPT
43
{
44
return error_condition(ev, *this);
45
}
46
47
bool
48
error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
49
{
50
return default_error_condition(code) == condition;
51
}
52
53
bool
54
error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
55
{
56
return *this == code.category() && code.value() == condition;
57
}
58
59
#if !defined(_LIBCPP_HAS_NO_THREADS)
60
namespace {
61
62
// GLIBC also uses 1024 as the maximum buffer size internally.
63
constexpr size_t strerror_buff_size = 1024;
64
65
string do_strerror_r(int ev);
66
67
#if defined(_LIBCPP_MSVCRT_LIKE)
68
string do_strerror_r(int ev) {
69
char buffer[strerror_buff_size];
70
if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
71
return string(buffer);
72
std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
73
return string(buffer);
74
}
75
#else
76
77
// Only one of the two following functions will be used, depending on
78
// the return type of strerror_r:
79
80
// For the GNU variant, a char* return value:
81
__attribute__((unused)) const char *
82
handle_strerror_r_return(char *strerror_return, char *buffer) {
83
// GNU always returns a string pointer in its return value. The
84
// string might point to either the input buffer, or a static
85
// buffer, but we don't care which.
86
return strerror_return;
87
}
88
89
// For the POSIX variant: an int return value.
90
__attribute__((unused)) const char *
91
handle_strerror_r_return(int strerror_return, char *buffer) {
92
// The POSIX variant either:
93
// - fills in the provided buffer and returns 0
94
// - returns a positive error value, or
95
// - returns -1 and fills in errno with an error value.
96
if (strerror_return == 0)
97
return buffer;
98
99
// Only handle EINVAL. Other errors abort.
100
int new_errno = strerror_return == -1 ? errno : strerror_return;
101
if (new_errno == EINVAL)
102
return "";
103
104
_LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
105
// FIXME maybe? 'strerror_buff_size' is likely to exceed the
106
// maximum error size so ERANGE shouldn't be returned.
107
std::abort();
108
}
109
110
// This function handles both GNU and POSIX variants, dispatching to
111
// one of the two above functions.
112
string do_strerror_r(int ev) {
113
char buffer[strerror_buff_size];
114
// Preserve errno around the call. (The C++ standard requires that
115
// system_error functions not modify errno).
116
const int old_errno = errno;
117
const char *error_message = handle_strerror_r_return(
118
::strerror_r(ev, buffer, strerror_buff_size), buffer);
119
// If we didn't get any message, print one now.
120
if (!error_message[0]) {
121
std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
122
error_message = buffer;
123
}
124
errno = old_errno;
125
return string(error_message);
126
}
127
#endif
128
} // end namespace
129
#endif
130
131
string
132
__do_message::message(int ev) const
133
{
134
#if defined(_LIBCPP_HAS_NO_THREADS)
135
return string(::strerror(ev));
136
#else
137
return do_strerror_r(ev);
138
#endif
139
}
140
141
class _LIBCPP_HIDDEN __generic_error_category
142
: public __do_message
143
{
144
public:
145
virtual const char* name() const _NOEXCEPT;
146
virtual string message(int ev) const;
147
};
148
149
const char*
150
__generic_error_category::name() const _NOEXCEPT
151
{
152
return "generic";
153
}
154
155
string
156
__generic_error_category::message(int ev) const
157
{
158
#ifdef _LIBCPP_ELAST
159
if (ev > _LIBCPP_ELAST)
160
return string("unspecified generic_category error");
161
#endif // _LIBCPP_ELAST
162
return __do_message::message(ev);
163
}
164
165
const error_category&
166
generic_category() _NOEXCEPT
167
{
168
static __generic_error_category s;
169
return s;
170
}
171
172
class _LIBCPP_HIDDEN __system_error_category
173
: public __do_message
174
{
175
public:
176
virtual const char* name() const _NOEXCEPT;
177
virtual string message(int ev) const;
178
virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
179
};
180
181
const char*
182
__system_error_category::name() const _NOEXCEPT
183
{
184
return "system";
185
}
186
187
string
188
__system_error_category::message(int ev) const
189
{
190
#ifdef _LIBCPP_ELAST
191
if (ev > _LIBCPP_ELAST)
192
return string("unspecified system_category error");
193
#endif // _LIBCPP_ELAST
194
return __do_message::message(ev);
195
}
196
197
error_condition
198
__system_error_category::default_error_condition(int ev) const _NOEXCEPT
199
{
200
#ifdef _LIBCPP_ELAST
201
if (ev > _LIBCPP_ELAST)
202
return error_condition(ev, system_category());
203
#endif // _LIBCPP_ELAST
204
return error_condition(ev, generic_category());
205
}
206
207
const error_category&
208
system_category() _NOEXCEPT
209
{
210
static __system_error_category s;
211
return s;
212
}
213
214
// error_condition
215
216
string
217
error_condition::message() const
218
{
219
return __cat_->message(__val_);
220
}
221
222
// error_code
223
224
string
225
error_code::message() const
226
{
227
return __cat_->message(__val_);
228
}
229
230
// system_error
231
232
string
233
system_error::__init(const error_code& ec, string what_arg)
234
{
235
if (ec)
236
{
237
if (!what_arg.empty())
238
what_arg += ": ";
239
what_arg += ec.message();
240
}
241
return what_arg;
242
}
243
244
system_error::system_error(error_code ec, const string& what_arg)
245
: runtime_error(__init(ec, what_arg)),
246
__ec_(ec)
247
{
248
}
249
250
system_error::system_error(error_code ec, const char* what_arg)
251
: runtime_error(__init(ec, what_arg)),
252
__ec_(ec)
253
{
254
}
255
256
system_error::system_error(error_code ec)
257
: runtime_error(__init(ec, "")),
258
__ec_(ec)
259
{
260
}
261
262
system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
263
: runtime_error(__init(error_code(ev, ecat), what_arg)),
264
__ec_(error_code(ev, ecat))
265
{
266
}
267
268
system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
269
: runtime_error(__init(error_code(ev, ecat), what_arg)),
270
__ec_(error_code(ev, ecat))
271
{
272
}
273
274
system_error::system_error(int ev, const error_category& ecat)
275
: runtime_error(__init(error_code(ev, ecat), "")),
276
__ec_(error_code(ev, ecat))
277
{
278
}
279
280
system_error::~system_error() _NOEXCEPT
281
{
282
}
283
284
void
285
__throw_system_error(int ev, const char* what_arg)
286
{
287
#ifndef _LIBCPP_NO_EXCEPTIONS
288
throw system_error(error_code(ev, system_category()), what_arg);
289
#else
290
(void)ev;
291
(void)what_arg;
292
_VSTD::abort();
293
#endif
294
}
295
296
_LIBCPP_END_NAMESPACE_STD
297
298