[44] | 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 | |
---|