xref: /netbsd-src/external/bsd/atf/dist/atf-c++/detail/exceptions.cpp (revision a551a20f66d65b75aa4c2dddf3e2e6f08dbfaf61)
1895f502bSjmmv //
2895f502bSjmmv // Automated Testing Framework (atf)
3895f502bSjmmv //
4*a551a20fSjmmv // Copyright (c) 2007 The NetBSD Foundation, Inc.
5895f502bSjmmv // All rights reserved.
6895f502bSjmmv //
7895f502bSjmmv // Redistribution and use in source and binary forms, with or without
8895f502bSjmmv // modification, are permitted provided that the following conditions
9895f502bSjmmv // are met:
10895f502bSjmmv // 1. Redistributions of source code must retain the above copyright
11895f502bSjmmv //    notice, this list of conditions and the following disclaimer.
12895f502bSjmmv // 2. Redistributions in binary form must reproduce the above copyright
13895f502bSjmmv //    notice, this list of conditions and the following disclaimer in the
14895f502bSjmmv //    documentation and/or other materials provided with the distribution.
15895f502bSjmmv //
16895f502bSjmmv // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17895f502bSjmmv // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18895f502bSjmmv // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19895f502bSjmmv // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20895f502bSjmmv // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21895f502bSjmmv // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22895f502bSjmmv // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23895f502bSjmmv // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24895f502bSjmmv // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25895f502bSjmmv // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26895f502bSjmmv // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27895f502bSjmmv // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28895f502bSjmmv //
29895f502bSjmmv 
30895f502bSjmmv #if defined(HAVE_CONFIG_H)
31895f502bSjmmv #include "bconfig.h"
32895f502bSjmmv #endif
33895f502bSjmmv 
34895f502bSjmmv #include <cstdarg>
35895f502bSjmmv #include <cstdio>
36895f502bSjmmv #include <cstring>
37eb215e31Sjmmv #include <new>
38895f502bSjmmv 
39895f502bSjmmv extern "C" {
40895f502bSjmmv #include "../../atf-c/error.h"
41895f502bSjmmv };
42895f502bSjmmv 
43895f502bSjmmv #include "exceptions.hpp"
44895f502bSjmmv #include "sanity.hpp"
45895f502bSjmmv 
46895f502bSjmmv // ------------------------------------------------------------------------
47895f502bSjmmv // The "system_error" type.
48895f502bSjmmv // ------------------------------------------------------------------------
49895f502bSjmmv 
system_error(const std::string & who,const std::string & message,int sys_err)50895f502bSjmmv atf::system_error::system_error(const std::string& who,
51895f502bSjmmv                                 const std::string& message,
52895f502bSjmmv                                 int sys_err) :
53895f502bSjmmv     std::runtime_error(who + ": " + message),
54895f502bSjmmv     m_sys_err(sys_err)
55895f502bSjmmv {
56895f502bSjmmv }
57895f502bSjmmv 
~system_error(void)58895f502bSjmmv atf::system_error::~system_error(void)
59895f502bSjmmv     throw()
60895f502bSjmmv {
61895f502bSjmmv }
62895f502bSjmmv 
63895f502bSjmmv int
code(void) const64895f502bSjmmv atf::system_error::code(void)
65895f502bSjmmv     const
66895f502bSjmmv     throw()
67895f502bSjmmv {
68895f502bSjmmv     return m_sys_err;
69895f502bSjmmv }
70895f502bSjmmv 
71895f502bSjmmv const char*
what(void) const72895f502bSjmmv atf::system_error::what(void)
73895f502bSjmmv     const
74895f502bSjmmv     throw()
75895f502bSjmmv {
76895f502bSjmmv     try {
77895f502bSjmmv         if (m_message.length() == 0) {
78895f502bSjmmv             m_message = std::string(std::runtime_error::what()) + ": ";
79895f502bSjmmv             m_message += ::strerror(m_sys_err);
80895f502bSjmmv         }
81895f502bSjmmv 
82895f502bSjmmv         return m_message.c_str();
83895f502bSjmmv     } catch (...) {
84895f502bSjmmv         return "Unable to format system_error message";
85895f502bSjmmv     }
86895f502bSjmmv }
87895f502bSjmmv 
88895f502bSjmmv // ------------------------------------------------------------------------
89895f502bSjmmv // Free functions.
90895f502bSjmmv // ------------------------------------------------------------------------
91895f502bSjmmv 
92895f502bSjmmv static
93895f502bSjmmv void
throw_libc_error(atf_error_t err)94895f502bSjmmv throw_libc_error(atf_error_t err)
95895f502bSjmmv {
96895f502bSjmmv     PRE(atf_error_is(err, "libc"));
97895f502bSjmmv 
98895f502bSjmmv     const int ecode = atf_libc_error_code(err);
99895f502bSjmmv     const std::string msg = atf_libc_error_msg(err);
100895f502bSjmmv     atf_error_free(err);
101895f502bSjmmv     throw atf::system_error("XXX", msg, ecode);
102895f502bSjmmv }
103895f502bSjmmv 
104895f502bSjmmv static
105895f502bSjmmv void
throw_no_memory_error(atf_error_t err)106895f502bSjmmv throw_no_memory_error(atf_error_t err)
107895f502bSjmmv {
108895f502bSjmmv     PRE(atf_error_is(err, "no_memory"));
109895f502bSjmmv 
110895f502bSjmmv     atf_error_free(err);
111895f502bSjmmv     throw std::bad_alloc();
112895f502bSjmmv }
113895f502bSjmmv 
114895f502bSjmmv static
115895f502bSjmmv void
throw_unknown_error(atf_error_t err)116895f502bSjmmv throw_unknown_error(atf_error_t err)
117895f502bSjmmv {
118895f502bSjmmv     PRE(atf_is_error(err));
119895f502bSjmmv 
120895f502bSjmmv     static char buf[4096];
121895f502bSjmmv     atf_error_format(err, buf, sizeof(buf));
122895f502bSjmmv     atf_error_free(err);
123895f502bSjmmv     throw std::runtime_error(buf);
124895f502bSjmmv }
125895f502bSjmmv 
126895f502bSjmmv void
throw_atf_error(atf_error_t err)127895f502bSjmmv atf::throw_atf_error(atf_error_t err)
128895f502bSjmmv {
129895f502bSjmmv     static struct handler {
130895f502bSjmmv         const char* m_name;
131895f502bSjmmv         void (*m_func)(atf_error_t);
132895f502bSjmmv     } handlers[] = {
133895f502bSjmmv         { "libc", throw_libc_error },
134895f502bSjmmv         { "no_memory", throw_no_memory_error },
135895f502bSjmmv         { NULL, throw_unknown_error },
136895f502bSjmmv     };
137895f502bSjmmv 
138895f502bSjmmv     PRE(atf_is_error(err));
139895f502bSjmmv 
140895f502bSjmmv     handler* h = handlers;
141895f502bSjmmv     while (h->m_name != NULL) {
142895f502bSjmmv         if (atf_error_is(err, h->m_name)) {
143895f502bSjmmv             h->m_func(err);
144895f502bSjmmv             UNREACHABLE;
145895f502bSjmmv         } else
146895f502bSjmmv             h++;
147895f502bSjmmv     }
148895f502bSjmmv     // XXX: I'm not sure that raising an "unknown" error is a wise thing
149895f502bSjmmv     // to do here.  The C++ binding is supposed to have feature parity
150895f502bSjmmv     // with the C one, so all possible errors raised by the C library
151895f502bSjmmv     // should have their counterpart in the C++ library.  Still, removing
152895f502bSjmmv     // this will require some code auditing that I can't afford at the
153895f502bSjmmv     // moment.
154895f502bSjmmv     INV(h->m_name == NULL && h->m_func != NULL);
155895f502bSjmmv     h->m_func(err);
156895f502bSjmmv     UNREACHABLE;
157895f502bSjmmv }
158