1 | // boost/catch_exceptions.hpp -----------------------------------------------// |
---|
2 | |
---|
3 | // Copyright Beman Dawes 1995-2001. Distributed under the Boost |
---|
4 | // Software License, Version 1.0. (See accompanying file |
---|
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
---|
6 | |
---|
7 | // See http://www.boost.org/libs/test for documentation. |
---|
8 | |
---|
9 | // Revision History |
---|
10 | // 13 Jun 01 report_exception() made inline. (John Maddock, Jesse Jones) |
---|
11 | // 26 Feb 01 Numerous changes suggested during formal review. (Beman) |
---|
12 | // 25 Jan 01 catch_exceptions.hpp code factored out of cpp_main.cpp. |
---|
13 | // 22 Jan 01 Remove test_tools dependencies to reduce coupling. |
---|
14 | // 5 Nov 00 Initial boost version (Beman Dawes) |
---|
15 | |
---|
16 | #ifndef BOOST_CATCH_EXCEPTIONS_HPP |
---|
17 | #define BOOST_CATCH_EXCEPTIONS_HPP |
---|
18 | |
---|
19 | // header dependencies are deliberately restricted to the standard library |
---|
20 | // to reduce coupling to other boost libraries. |
---|
21 | #include <string> // for string |
---|
22 | #include <new> // for bad_alloc |
---|
23 | #include <typeinfo> // for bad_cast, bad_typeid |
---|
24 | #include <exception> // for exception, bad_exception |
---|
25 | #include <stdexcept> // for std exception hierarchy |
---|
26 | #include <boost/cstdlib.hpp> // for exit codes |
---|
27 | # if __GNUC__ != 2 || __GNUC_MINOR__ > 96 |
---|
28 | # include <ostream> // for ostream |
---|
29 | # else |
---|
30 | # include <iostream> // workaround GNU missing ostream header |
---|
31 | # endif |
---|
32 | |
---|
33 | # if defined(__BORLANDC__) && (__BORLANDC__ <= 0x0551) |
---|
34 | # define BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT |
---|
35 | # endif |
---|
36 | |
---|
37 | #if defined(MPW_CPLUS) && (MPW_CPLUS <= 0x890) |
---|
38 | # define BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT |
---|
39 | namespace std { class bad_typeid { }; } |
---|
40 | # endif |
---|
41 | |
---|
42 | namespace boost |
---|
43 | { |
---|
44 | |
---|
45 | namespace detail |
---|
46 | { |
---|
47 | // A separate reporting function was requested during formal review. |
---|
48 | inline void report_exception( std::ostream & os, |
---|
49 | const char * name, const char * info ) |
---|
50 | { os << "\n** uncaught exception: " << name << " " << info << std::endl; } |
---|
51 | } |
---|
52 | |
---|
53 | // catch_exceptions ------------------------------------------------------// |
---|
54 | |
---|
55 | template< class Generator > // Generator is function object returning int |
---|
56 | int catch_exceptions( Generator function_object, |
---|
57 | std::ostream & out, std::ostream & err ) |
---|
58 | { |
---|
59 | int result = 0; // quiet compiler warnings |
---|
60 | bool exception_thrown = true; // avoid setting result for each excptn type |
---|
61 | |
---|
62 | #ifndef BOOST_NO_EXCEPTIONS |
---|
63 | try |
---|
64 | { |
---|
65 | #endif |
---|
66 | result = function_object(); |
---|
67 | exception_thrown = false; |
---|
68 | #ifndef BOOST_NO_EXCEPTIONS |
---|
69 | } |
---|
70 | |
---|
71 | // As a result of hard experience with strangely interleaved output |
---|
72 | // under some compilers, there is a lot of use of endl in the code below |
---|
73 | // where a simple '\n' might appear to do. |
---|
74 | |
---|
75 | // The rules for catch & arguments are a bit different from function |
---|
76 | // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't |
---|
77 | // required, but it doesn't hurt and some programmers ask for it. |
---|
78 | |
---|
79 | catch ( const char * ex ) |
---|
80 | { detail::report_exception( out, "", ex ); } |
---|
81 | catch ( const std::string & ex ) |
---|
82 | { detail::report_exception( out, "", ex.c_str() ); } |
---|
83 | |
---|
84 | // std:: exceptions |
---|
85 | catch ( const std::bad_alloc & ex ) |
---|
86 | { detail::report_exception( out, "std::bad_alloc:", ex.what() ); } |
---|
87 | |
---|
88 | # ifndef BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT |
---|
89 | catch ( const std::bad_cast & ex ) |
---|
90 | { detail::report_exception( out, "std::bad_cast:", ex.what() ); } |
---|
91 | catch ( const std::bad_typeid & ex ) |
---|
92 | { detail::report_exception( out, "std::bad_typeid:", ex.what() ); } |
---|
93 | # else |
---|
94 | catch ( const std::bad_cast & ) |
---|
95 | { detail::report_exception( out, "std::bad_cast", "" ); } |
---|
96 | catch ( const std::bad_typeid & ) |
---|
97 | { detail::report_exception( out, "std::bad_typeid", "" ); } |
---|
98 | # endif |
---|
99 | |
---|
100 | catch ( const std::bad_exception & ex ) |
---|
101 | { detail::report_exception( out, "std::bad_exception:", ex.what() ); } |
---|
102 | catch ( const std::domain_error & ex ) |
---|
103 | { detail::report_exception( out, "std::domain_error:", ex.what() ); } |
---|
104 | catch ( const std::invalid_argument & ex ) |
---|
105 | { detail::report_exception( out, "std::invalid_argument:", ex.what() ); } |
---|
106 | catch ( const std::length_error & ex ) |
---|
107 | { detail::report_exception( out, "std::length_error:", ex.what() ); } |
---|
108 | catch ( const std::out_of_range & ex ) |
---|
109 | { detail::report_exception( out, "std::out_of_range:", ex.what() ); } |
---|
110 | catch ( const std::range_error & ex ) |
---|
111 | { detail::report_exception( out, "std::range_error:", ex.what() ); } |
---|
112 | catch ( const std::overflow_error & ex ) |
---|
113 | { detail::report_exception( out, "std::overflow_error:", ex.what() ); } |
---|
114 | catch ( const std::underflow_error & ex ) |
---|
115 | { detail::report_exception( out, "std::underflow_error:", ex.what() ); } |
---|
116 | catch ( const std::logic_error & ex ) |
---|
117 | { detail::report_exception( out, "std::logic_error:", ex.what() ); } |
---|
118 | catch ( const std::runtime_error & ex ) |
---|
119 | { detail::report_exception( out, "std::runtime_error:", ex.what() ); } |
---|
120 | catch ( const std::exception & ex ) |
---|
121 | { detail::report_exception( out, "std::exception:", ex.what() ); } |
---|
122 | |
---|
123 | catch ( ... ) |
---|
124 | { detail::report_exception( out, "unknown exception", "" ); } |
---|
125 | #endif // BOOST_NO_EXCEPTIONS |
---|
126 | |
---|
127 | if ( exception_thrown ) result = boost::exit_exception_failure; |
---|
128 | |
---|
129 | if ( result != 0 && result != exit_success ) |
---|
130 | { |
---|
131 | out << std::endl << "**** returning with error code " |
---|
132 | << result << std::endl; |
---|
133 | err |
---|
134 | << "********** errors detected; see stdout for details ***********" |
---|
135 | << std::endl; |
---|
136 | } |
---|
137 | #if !defined(BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE) |
---|
138 | else { out << std::flush << "no errors detected" << std::endl; } |
---|
139 | #endif |
---|
140 | return result; |
---|
141 | } // catch_exceptions |
---|
142 | |
---|
143 | } // boost |
---|
144 | |
---|
145 | #endif // BOOST_CATCH_EXCEPTIONS_HPP |
---|
146 | |
---|