1 | // error_code support implementation file ----------------------------------// |
2 | |
3 | // Copyright Beman Dawes 2002, 2006 |
4 | // Copyright (c) Microsoft Corporation 2014 |
5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
7 | |
8 | // See library home page at http://www.boost.org/libs/system |
9 | |
10 | //----------------------------------------------------------------------------// |
11 | |
12 | #include <boost/config/warning_disable.hpp> |
13 | |
14 | #include <boost/system/config.hpp> |
15 | #include <boost/system/error_code.hpp> |
16 | #include <boost/cerrno.hpp> |
17 | #include <vector> |
18 | #include <cstdlib> |
19 | #include <cassert> |
20 | |
21 | #include <cstring> // for strerror/strerror_r |
22 | |
23 | # if defined( BOOST_WINDOWS_API ) |
24 | # include <windows.h> |
25 | # if !BOOST_PLAT_WINDOWS_RUNTIME |
26 | # include <boost/system/detail/local_free_on_destruction.hpp> |
27 | # endif |
28 | # ifndef ERROR_INCORRECT_SIZE |
29 | # define ERROR_INCORRECT_SIZE ERROR_BAD_ARGUMENTS |
30 | # endif |
31 | # endif |
32 | |
33 | //----------------------------------------------------------------------------// |
34 | namespace boost |
35 | { |
36 | namespace system |
37 | { |
38 | |
39 | namespace |
40 | { |
41 | |
42 | // standard error categories ---------------------------------------------// |
43 | |
44 | class generic_error_category : public error_category |
45 | { |
46 | public: |
47 | generic_error_category(){} |
48 | const char * name() const BOOST_SYSTEM_NOEXCEPT; |
49 | std::string message( int ev ) const; |
50 | }; |
51 | |
52 | class system_error_category : public error_category |
53 | { |
54 | public: |
55 | system_error_category(){} |
56 | const char * name() const BOOST_SYSTEM_NOEXCEPT; |
57 | std::string message( int ev ) const; |
58 | error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT; |
59 | }; |
60 | |
61 | // generic_error_category implementation ---------------------------------// |
62 | |
63 | const char * generic_error_category::name() const BOOST_SYSTEM_NOEXCEPT |
64 | { |
65 | return "generic" ; |
66 | } |
67 | |
68 | std::string generic_error_category::message( int ev ) const |
69 | { |
70 | using namespace boost::system::errc; |
71 | #if defined(__PGI) |
72 | using boost::system::errc::invalid_argument; |
73 | #endif |
74 | |
75 | static std::string unknown_err( "Unknown error" ); |
76 | // strerror_r is preferred because it is always thread safe, |
77 | // however, we fallback to strerror in certain cases because: |
78 | // -- Windows doesn't provide strerror_r. |
79 | // -- HP and Sun do provide strerror_r on newer systems, but there is |
80 | // no way to tell if is available at runtime and in any case their |
81 | // versions of strerror are thread safe anyhow. |
82 | // -- Linux only sometimes provides strerror_r. |
83 | // -- Tru64 provides strerror_r only when compiled -pthread. |
84 | // -- VMS doesn't provide strerror_r, but on this platform, strerror is |
85 | // thread safe. |
86 | # if defined(BOOST_WINDOWS_API) || defined(__hpux) || defined(__sun)\ |
87 | || (defined(__linux) && (!defined(__USE_XOPEN2K) || defined(BOOST_SYSTEM_USE_STRERROR)))\ |
88 | || (defined(__osf__) && !defined(_REENTRANT))\ |
89 | || (defined(__INTEGRITY))\ |
90 | || (defined(__vms))\ |
91 | || (defined(__QNXNTO__)) |
92 | const char * c_str = std::strerror( ev ); |
93 | return c_str |
94 | ? std::string( c_str ) |
95 | : unknown_err; |
96 | # else // use strerror_r |
97 | char buf[64]; |
98 | char * bp = buf; |
99 | std::size_t sz = sizeof(buf); |
100 | # if defined(__CYGWIN__) || defined(__USE_GNU) |
101 | // Oddball version of strerror_r |
102 | const char * c_str = strerror_r( errnum: ev, buf: bp, buflen: sz ); |
103 | return c_str |
104 | ? std::string( c_str ) |
105 | : unknown_err; |
106 | # else |
107 | // POSIX version of strerror_r |
108 | int result; |
109 | for (;;) |
110 | { |
111 | // strerror_r returns 0 on success, otherwise ERANGE if buffer too small, |
112 | // invalid_argument if ev not a valid error number |
113 | # if defined (__sgi) |
114 | const char * c_str = strerror( ev ); |
115 | result = 0; |
116 | return c_str |
117 | ? std::string( c_str ) |
118 | : unknown_err; |
119 | # else |
120 | result = strerror_r( ev, bp, sz ); |
121 | # endif |
122 | if (result == 0 ) |
123 | break; |
124 | else |
125 | { |
126 | # if defined(__linux) |
127 | // Linux strerror_r returns -1 on error, with error number in errno |
128 | result = errno; |
129 | # endif |
130 | if ( result != ERANGE ) break; |
131 | if ( sz > sizeof(buf) ) std::free( bp ); |
132 | sz *= 2; |
133 | if ( (bp = static_cast<char*>(std::malloc( sz ))) == 0 ) |
134 | return std::string( "ENOMEM" ); |
135 | } |
136 | } |
137 | std::string msg; |
138 | # ifndef BOOST_NO_EXCEPTIONS |
139 | try |
140 | # endif |
141 | { |
142 | msg = ( ( result == invalid_argument ) ? "Unknown error" : bp ); |
143 | } |
144 | |
145 | # ifndef BOOST_NO_EXCEPTIONS |
146 | // See ticket #2098 |
147 | catch(...) |
148 | { |
149 | // just eat the exception |
150 | } |
151 | # endif |
152 | |
153 | if ( sz > sizeof(buf) ) std::free( bp ); |
154 | sz = 0; |
155 | return msg; |
156 | # endif // else POSIX version of strerror_r |
157 | # endif // else use strerror_r |
158 | } |
159 | // system_error_category implementation --------------------------------// |
160 | |
161 | const char * system_error_category::name() const BOOST_SYSTEM_NOEXCEPT |
162 | { |
163 | return "system" ; |
164 | } |
165 | |
166 | error_condition system_error_category::default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT |
167 | { |
168 | using namespace boost::system::errc; |
169 | #if defined(__PGI) |
170 | using boost::system::errc::invalid_argument; |
171 | #endif |
172 | |
173 | # if defined(BOOST_WINDOWS_API) |
174 | # if defined(WINAPI_FAMILY) && ((WINAPI_FAMILY & WINAPI_PARTITION_APP) != 0) |
175 | // When using the Windows Runtime, most system errors are reported as HRESULTs. |
176 | // We want to map the common Win32 errors to their equivalent error condition, |
177 | // whether or not they are reported via an HRESULT. |
178 | if ( ev < 0 ) // Check for failed HRESULTs only. |
179 | if ( HRESULT_FACILITY( ev ) == FACILITY_WIN32 ) |
180 | ev = HRESULT_CODE( ev ); |
181 | # endif |
182 | # endif |
183 | |
184 | switch ( ev ) |
185 | { |
186 | case 0: return make_error_condition( e: success ); |
187 | # if defined(BOOST_POSIX_API) |
188 | // POSIX-like O/S -> posix_errno decode table ---------------------------// |
189 | case E2BIG: return make_error_condition( e: argument_list_too_long ); |
190 | case EACCES: return make_error_condition( e: permission_denied ); |
191 | case EADDRINUSE: return make_error_condition( e: address_in_use ); |
192 | case EADDRNOTAVAIL: return make_error_condition( e: address_not_available ); |
193 | case EAFNOSUPPORT: return make_error_condition( e: address_family_not_supported ); |
194 | case EAGAIN: return make_error_condition( e: resource_unavailable_try_again ); |
195 | # if EALREADY != EBUSY // EALREADY and EBUSY are the same on QNX Neutrino |
196 | case EALREADY: return make_error_condition( e: connection_already_in_progress ); |
197 | # endif |
198 | case EBADF: return make_error_condition( e: bad_file_descriptor ); |
199 | case EBADMSG: return make_error_condition( e: bad_message ); |
200 | case EBUSY: return make_error_condition( e: device_or_resource_busy ); |
201 | case ECANCELED: return make_error_condition( e: operation_canceled ); |
202 | case ECHILD: return make_error_condition( e: no_child_process ); |
203 | case ECONNABORTED: return make_error_condition( e: connection_aborted ); |
204 | case ECONNREFUSED: return make_error_condition( e: connection_refused ); |
205 | case ECONNRESET: return make_error_condition( e: connection_reset ); |
206 | case EDEADLK: return make_error_condition( e: resource_deadlock_would_occur ); |
207 | case EDESTADDRREQ: return make_error_condition( e: destination_address_required ); |
208 | case EDOM: return make_error_condition( e: argument_out_of_domain ); |
209 | case EEXIST: return make_error_condition( e: file_exists ); |
210 | case EFAULT: return make_error_condition( e: bad_address ); |
211 | case EFBIG: return make_error_condition( e: file_too_large ); |
212 | case EHOSTUNREACH: return make_error_condition( e: host_unreachable ); |
213 | case EIDRM: return make_error_condition( e: identifier_removed ); |
214 | case EILSEQ: return make_error_condition( e: illegal_byte_sequence ); |
215 | case EINPROGRESS: return make_error_condition( e: operation_in_progress ); |
216 | case EINTR: return make_error_condition( e: interrupted ); |
217 | case EINVAL: return make_error_condition( e: invalid_argument ); |
218 | case EIO: return make_error_condition( e: io_error ); |
219 | case EISCONN: return make_error_condition( e: already_connected ); |
220 | case EISDIR: return make_error_condition( e: is_a_directory ); |
221 | case ELOOP: return make_error_condition( e: too_many_symbolic_link_levels ); |
222 | case EMFILE: return make_error_condition( e: too_many_files_open ); |
223 | case EMLINK: return make_error_condition( e: too_many_links ); |
224 | case EMSGSIZE: return make_error_condition( e: message_size ); |
225 | case ENAMETOOLONG: return make_error_condition( e: filename_too_long ); |
226 | case ENETDOWN: return make_error_condition( e: network_down ); |
227 | case ENETRESET: return make_error_condition( e: network_reset ); |
228 | case ENETUNREACH: return make_error_condition( e: network_unreachable ); |
229 | case ENFILE: return make_error_condition( e: too_many_files_open_in_system ); |
230 | case ENOBUFS: return make_error_condition( e: no_buffer_space ); |
231 | case ENODATA: return make_error_condition( e: no_message_available ); |
232 | case ENODEV: return make_error_condition( e: no_such_device ); |
233 | case ENOENT: return make_error_condition( e: no_such_file_or_directory ); |
234 | case ENOEXEC: return make_error_condition( e: executable_format_error ); |
235 | case ENOLCK: return make_error_condition( e: no_lock_available ); |
236 | case ENOLINK: return make_error_condition( e: no_link ); |
237 | case ENOMEM: return make_error_condition( e: not_enough_memory ); |
238 | case ENOMSG: return make_error_condition( e: no_message ); |
239 | case ENOPROTOOPT: return make_error_condition( e: no_protocol_option ); |
240 | case ENOSPC: return make_error_condition( e: no_space_on_device ); |
241 | case ENOSR: return make_error_condition( e: no_stream_resources ); |
242 | case ENOSTR: return make_error_condition( e: not_a_stream ); |
243 | case ENOSYS: return make_error_condition( e: function_not_supported ); |
244 | case ENOTCONN: return make_error_condition( e: not_connected ); |
245 | case ENOTDIR: return make_error_condition( e: not_a_directory ); |
246 | # if ENOTEMPTY != EEXIST // AIX treats ENOTEMPTY and EEXIST as the same value |
247 | case ENOTEMPTY: return make_error_condition( e: directory_not_empty ); |
248 | # endif // ENOTEMPTY != EEXIST |
249 | # if ENOTRECOVERABLE != ECONNRESET // the same on some Broadcom chips |
250 | case ENOTRECOVERABLE: return make_error_condition( e: state_not_recoverable ); |
251 | # endif // ENOTRECOVERABLE != ECONNRESET |
252 | case ENOTSOCK: return make_error_condition( e: not_a_socket ); |
253 | case ENOTSUP: return make_error_condition( e: not_supported ); |
254 | case ENOTTY: return make_error_condition( e: inappropriate_io_control_operation ); |
255 | case ENXIO: return make_error_condition( e: no_such_device_or_address ); |
256 | # if EOPNOTSUPP != ENOTSUP |
257 | case EOPNOTSUPP: return make_error_condition( operation_not_supported ); |
258 | # endif // EOPNOTSUPP != ENOTSUP |
259 | case EOVERFLOW: return make_error_condition( e: value_too_large ); |
260 | # if EOWNERDEAD != ECONNABORTED // the same on some Broadcom chips |
261 | case EOWNERDEAD: return make_error_condition( e: owner_dead ); |
262 | # endif // EOWNERDEAD != ECONNABORTED |
263 | case EPERM: return make_error_condition( e: operation_not_permitted ); |
264 | case EPIPE: return make_error_condition( e: broken_pipe ); |
265 | case EPROTO: return make_error_condition( e: protocol_error ); |
266 | case EPROTONOSUPPORT: return make_error_condition( e: protocol_not_supported ); |
267 | case EPROTOTYPE: return make_error_condition( e: wrong_protocol_type ); |
268 | case ERANGE: return make_error_condition( e: result_out_of_range ); |
269 | case EROFS: return make_error_condition( e: read_only_file_system ); |
270 | case ESPIPE: return make_error_condition( e: invalid_seek ); |
271 | case ESRCH: return make_error_condition( e: no_such_process ); |
272 | case ETIME: return make_error_condition( e: stream_timeout ); |
273 | case ETIMEDOUT: return make_error_condition( e: timed_out ); |
274 | case ETXTBSY: return make_error_condition( e: text_file_busy ); |
275 | # if EAGAIN != EWOULDBLOCK |
276 | case EWOULDBLOCK: return make_error_condition( operation_would_block ); |
277 | # endif // EAGAIN != EWOULDBLOCK |
278 | case EXDEV: return make_error_condition( e: cross_device_link ); |
279 | #else |
280 | // Windows system -> posix_errno decode table ---------------------------// |
281 | // see WinError.h comments for descriptions of errors |
282 | case ERROR_ACCESS_DENIED: return make_error_condition( permission_denied ); |
283 | case ERROR_ALREADY_EXISTS: return make_error_condition( file_exists ); |
284 | case ERROR_BAD_UNIT: return make_error_condition( no_such_device ); |
285 | case ERROR_BUFFER_OVERFLOW: return make_error_condition( filename_too_long ); |
286 | case ERROR_BUSY: return make_error_condition( device_or_resource_busy ); |
287 | case ERROR_BUSY_DRIVE: return make_error_condition( device_or_resource_busy ); |
288 | case ERROR_CANNOT_MAKE: return make_error_condition( permission_denied ); |
289 | case ERROR_CANTOPEN: return make_error_condition( io_error ); |
290 | case ERROR_CANTREAD: return make_error_condition( io_error ); |
291 | case ERROR_CANTWRITE: return make_error_condition( io_error ); |
292 | case ERROR_CURRENT_DIRECTORY: return make_error_condition( permission_denied ); |
293 | case ERROR_DEV_NOT_EXIST: return make_error_condition( no_such_device ); |
294 | case ERROR_DEVICE_IN_USE: return make_error_condition( device_or_resource_busy ); |
295 | case ERROR_DIR_NOT_EMPTY: return make_error_condition( directory_not_empty ); |
296 | case ERROR_DIRECTORY: return make_error_condition( invalid_argument ); // WinError.h: "The directory name is invalid" |
297 | case ERROR_DISK_FULL: return make_error_condition( no_space_on_device ); |
298 | case ERROR_FILE_EXISTS: return make_error_condition( file_exists ); |
299 | case ERROR_FILE_NOT_FOUND: return make_error_condition( no_such_file_or_directory ); |
300 | case ERROR_HANDLE_DISK_FULL: return make_error_condition( no_space_on_device ); |
301 | case ERROR_INVALID_ACCESS: return make_error_condition( permission_denied ); |
302 | case ERROR_INVALID_DRIVE: return make_error_condition( no_such_device ); |
303 | case ERROR_INVALID_FUNCTION: return make_error_condition( function_not_supported ); |
304 | case ERROR_INVALID_HANDLE: return make_error_condition( invalid_argument ); |
305 | case ERROR_INVALID_NAME: return make_error_condition( invalid_argument ); |
306 | case ERROR_LOCK_VIOLATION: return make_error_condition( no_lock_available ); |
307 | case ERROR_LOCKED: return make_error_condition( no_lock_available ); |
308 | case ERROR_NEGATIVE_SEEK: return make_error_condition( invalid_argument ); |
309 | case ERROR_NOACCESS: return make_error_condition( permission_denied ); |
310 | case ERROR_NOT_ENOUGH_MEMORY: return make_error_condition( not_enough_memory ); |
311 | case ERROR_NOT_READY: return make_error_condition( resource_unavailable_try_again ); |
312 | case ERROR_NOT_SAME_DEVICE: return make_error_condition( cross_device_link ); |
313 | case ERROR_OPEN_FAILED: return make_error_condition( io_error ); |
314 | case ERROR_OPEN_FILES: return make_error_condition( device_or_resource_busy ); |
315 | case ERROR_OPERATION_ABORTED: return make_error_condition( operation_canceled ); |
316 | case ERROR_OUTOFMEMORY: return make_error_condition( not_enough_memory ); |
317 | case ERROR_PATH_NOT_FOUND: return make_error_condition( no_such_file_or_directory ); |
318 | case ERROR_READ_FAULT: return make_error_condition( io_error ); |
319 | case ERROR_RETRY: return make_error_condition( resource_unavailable_try_again ); |
320 | case ERROR_SEEK: return make_error_condition( io_error ); |
321 | case ERROR_SHARING_VIOLATION: return make_error_condition( permission_denied ); |
322 | case ERROR_TOO_MANY_OPEN_FILES: return make_error_condition( too_many_files_open ); |
323 | case ERROR_WRITE_FAULT: return make_error_condition( io_error ); |
324 | case ERROR_WRITE_PROTECT: return make_error_condition( permission_denied ); |
325 | case WSAEACCES: return make_error_condition( permission_denied ); |
326 | case WSAEADDRINUSE: return make_error_condition( address_in_use ); |
327 | case WSAEADDRNOTAVAIL: return make_error_condition( address_not_available ); |
328 | case WSAEAFNOSUPPORT: return make_error_condition( address_family_not_supported ); |
329 | case WSAEALREADY: return make_error_condition( connection_already_in_progress ); |
330 | case WSAEBADF: return make_error_condition( bad_file_descriptor ); |
331 | case WSAECONNABORTED: return make_error_condition( connection_aborted ); |
332 | case WSAECONNREFUSED: return make_error_condition( connection_refused ); |
333 | case WSAECONNRESET: return make_error_condition( connection_reset ); |
334 | case WSAEDESTADDRREQ: return make_error_condition( destination_address_required ); |
335 | case WSAEFAULT: return make_error_condition( bad_address ); |
336 | case WSAEHOSTUNREACH: return make_error_condition( host_unreachable ); |
337 | case WSAEINPROGRESS: return make_error_condition( operation_in_progress ); |
338 | case WSAEINTR: return make_error_condition( interrupted ); |
339 | case WSAEINVAL: return make_error_condition( invalid_argument ); |
340 | case WSAEISCONN: return make_error_condition( already_connected ); |
341 | case WSAEMFILE: return make_error_condition( too_many_files_open ); |
342 | case WSAEMSGSIZE: return make_error_condition( message_size ); |
343 | case WSAENAMETOOLONG: return make_error_condition( filename_too_long ); |
344 | case WSAENETDOWN: return make_error_condition( network_down ); |
345 | case WSAENETRESET: return make_error_condition( network_reset ); |
346 | case WSAENETUNREACH: return make_error_condition( network_unreachable ); |
347 | case WSAENOBUFS: return make_error_condition( no_buffer_space ); |
348 | case WSAENOPROTOOPT: return make_error_condition( no_protocol_option ); |
349 | case WSAENOTCONN: return make_error_condition( not_connected ); |
350 | case WSAENOTSOCK: return make_error_condition( not_a_socket ); |
351 | case WSAEOPNOTSUPP: return make_error_condition( operation_not_supported ); |
352 | case WSAEPROTONOSUPPORT: return make_error_condition( protocol_not_supported ); |
353 | case WSAEPROTOTYPE: return make_error_condition( wrong_protocol_type ); |
354 | case WSAETIMEDOUT: return make_error_condition( timed_out ); |
355 | case WSAEWOULDBLOCK: return make_error_condition( operation_would_block ); |
356 | #endif |
357 | default: return error_condition( ev, system_category() ); |
358 | } |
359 | } |
360 | |
361 | # if !defined( BOOST_WINDOWS_API ) |
362 | |
363 | std::string system_error_category::message( int ev ) const |
364 | { |
365 | return generic_category().message( ev ); |
366 | } |
367 | # else |
368 | |
369 | std::string system_error_category::message( int ev ) const |
370 | { |
371 | #if defined(UNDER_CE) || BOOST_PLAT_WINDOWS_RUNTIME || defined(BOOST_NO_ANSI_APIS) |
372 | std::wstring buf(128, wchar_t()); |
373 | for (;;) |
374 | { |
375 | DWORD retval = ::FormatMessageW( |
376 | FORMAT_MESSAGE_FROM_SYSTEM | |
377 | FORMAT_MESSAGE_IGNORE_INSERTS, |
378 | NULL, |
379 | ev, |
380 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language |
381 | &buf[0], |
382 | buf.size(), |
383 | NULL |
384 | ); |
385 | |
386 | if (retval > 0) |
387 | { |
388 | buf.resize(retval); |
389 | break; |
390 | } |
391 | else if ( ::GetLastError() != ERROR_INSUFFICIENT_BUFFER ) |
392 | { |
393 | return std::string("Unknown error" ); |
394 | } |
395 | else |
396 | { |
397 | buf.resize(buf.size() + buf.size() / 2); |
398 | } |
399 | } |
400 | |
401 | int num_chars = (buf.size() + 1) * 2; |
402 | LPSTR narrow_buffer = (LPSTR)_alloca( num_chars ); |
403 | if (::WideCharToMultiByte(CP_ACP, 0, buf.c_str(), -1, narrow_buffer, num_chars, NULL, NULL) == 0) |
404 | { |
405 | return std::string("Unknown error" ); |
406 | } |
407 | |
408 | std::string str( narrow_buffer ); |
409 | #else |
410 | LPVOID lpMsgBuf = 0; |
411 | DWORD retval = ::FormatMessageA( |
412 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
413 | FORMAT_MESSAGE_FROM_SYSTEM | |
414 | FORMAT_MESSAGE_IGNORE_INSERTS, |
415 | NULL, |
416 | ev, |
417 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language |
418 | (LPSTR) &lpMsgBuf, |
419 | 0, |
420 | NULL |
421 | ); |
422 | detail::local_free_on_destruction lfod(lpMsgBuf); |
423 | if (retval == 0) |
424 | return std::string("Unknown error" ); |
425 | |
426 | std::string str( static_cast<LPCSTR>(lpMsgBuf) ); |
427 | # endif |
428 | while ( str.size() |
429 | && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') ) |
430 | str.erase( str.size()-1 ); |
431 | if ( str.size() && str[str.size()-1] == '.' ) |
432 | { str.erase( str.size()-1 ); } |
433 | return str; |
434 | } |
435 | # endif |
436 | |
437 | } // unnamed namespace |
438 | |
439 | |
440 | # ifndef BOOST_SYSTEM_NO_DEPRECATED |
441 | BOOST_SYSTEM_DECL error_code throws; // "throw on error" special error_code; |
442 | // note that it doesn't matter if this |
443 | // isn't initialized before use since |
444 | // the only use is to take its |
445 | // address for comparison purposes |
446 | # endif |
447 | |
448 | # ifdef BOOST_ERROR_CODE_HEADER_ONLY |
449 | # define BOOST_SYSTEM_LINKAGE inline |
450 | # else |
451 | # define BOOST_SYSTEM_LINKAGE BOOST_SYSTEM_DECL |
452 | # endif |
453 | |
454 | BOOST_SYSTEM_LINKAGE const error_category & system_category() BOOST_SYSTEM_NOEXCEPT |
455 | { |
456 | static const system_error_category system_category_const; |
457 | return system_category_const; |
458 | } |
459 | |
460 | BOOST_SYSTEM_LINKAGE const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT |
461 | { |
462 | static const generic_error_category generic_category_const; |
463 | return generic_category_const; |
464 | } |
465 | |
466 | } // namespace system |
467 | } // namespace boost |
468 | |