https://github.com/cran/Rcpp
Revision a5efaaa5edad752264a962eba18c2fe7b700f19e authored by Dirk Eddelbuettel and Romain Francois on 28 November 2010, 06:24:47 UTC, committed by cran-robot on 28 November 2010, 06:24:47 UTC
1 parent 521bd2d
Tip revision: a5efaaa5edad752264a962eba18c2fe7b700f19e authored by Dirk Eddelbuettel and Romain Francois on 28 November 2010, 06:24:47 UTC
version 0.8.9
version 0.8.9
Tip revision: a5efaaa
exceptions.cpp
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
//
// exceptions.cpp: R/C++ interface class library -- exception handling
//
// Copyright (C) 2009 - 2010 Dirk Eddelbuettel and Romain Francois
//
// This file is part of Rcpp.
//
// Rcpp is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// Rcpp is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
#include <Rcpp.h>
namespace Rcpp{
exception::exception( const char* message_, const char* file, int line) : message(message_){
rcpp_set_stack_trace( stack_trace(file,line) ) ;
}
exception::~exception() throw(){}
#define RCPP_EXCEPTION_WHAT(__CLASS__) \
const char* __CLASS__::what() const throw(){ return message.c_str(); }
RCPP_EXCEPTION_WHAT(exception)
RCPP_EXCEPTION_WHAT(not_compatible)
RCPP_EXCEPTION_WHAT(S4_creation_error)
RCPP_EXCEPTION_WHAT(reference_creation_error)
RCPP_EXCEPTION_WHAT(no_such_binding)
RCPP_EXCEPTION_WHAT(binding_not_found)
RCPP_EXCEPTION_WHAT(binding_is_locked)
RCPP_EXCEPTION_WHAT(no_such_namespace)
RCPP_EXCEPTION_WHAT(eval_error)
#undef RCPP_EXCEPTION_WHAT
#define RCPP_SIMPLE_EXCEPTION_WHAT(__CLASS__,__MESSAGE__) \
const char* __CLASS__::what() const throw(){ return __MESSAGE__ ; }
RCPP_SIMPLE_EXCEPTION_WHAT(not_a_matrix, "not a matrix" )
RCPP_SIMPLE_EXCEPTION_WHAT(index_out_of_bounds, "index out of bounds" )
RCPP_SIMPLE_EXCEPTION_WHAT(parse_error, "parse error")
RCPP_SIMPLE_EXCEPTION_WHAT(not_s4, "not an S4 object" )
RCPP_SIMPLE_EXCEPTION_WHAT(not_reference, "not a reference S4 object" )
RCPP_SIMPLE_EXCEPTION_WHAT(no_such_slot, "no such slot" )
RCPP_SIMPLE_EXCEPTION_WHAT(no_such_field, "no such field" )
RCPP_SIMPLE_EXCEPTION_WHAT(not_a_closure, "not a closure" )
RCPP_SIMPLE_EXCEPTION_WHAT(no_such_function, "no such function" )
RCPP_SIMPLE_EXCEPTION_WHAT(unevaluated_promise, "promise not yet evaluated" )
#undef RCPP_SIMPLE_EXCEPTION_WHAT
}
/* for now, the fancy exception handling is only available in GCC,
simply because we've not investigated if it is available in other
compilers */
#ifdef RCPP_HAS_DEMANGLING
#include <typeinfo>
#include <exception_defines.h>
#include <cxxabi.h>
std::string demangle( const std::string& name ){
std::string real_class ;
int status =-1 ;
char *dem = 0;
dem = abi::__cxa_demangle(name.c_str(), 0, 0, &status);
if( status == 0 ){
real_class = dem ;
free(dem);
} else {
real_class = name ;
}
return real_class ;
}
/* much inspired from the __verbose_terminate_handler of the GCC */
void forward_uncaught_exceptions_to_r(){
std::string exception_class ;
bool has_exception_class = false;
std::string exception_what ;
// Make sure there was an exception; terminate is also called for an
// attempt to rethrow when there is no suitable exception.
std::type_info *t = abi::__cxa_current_exception_type();
if (t){
has_exception_class = true ;
const char *name = t->name() ;
// now we need to demangle "name"
{
int status = -1;
char *dem = 0;
dem = abi::__cxa_demangle(name, 0, 0, &status);
if( status == 0){
exception_class = dem ; /* great we can use the demangled name */
free(dem);
} else{
exception_class = name ; /* just using the mangled name */
}
}
}
// If the exception is derived from std::exception, we can give more
// information.
try {
__throw_exception_again;
} catch (std::exception &exc) {
exception_what = exc.what() ;
} catch (...) {
exception_what = "unrecognized exception" ;
}
Rf_eval(
Rf_lang3(
Rf_install("cpp_exception"),
Rf_mkString(exception_what.c_str()),
has_exception_class ? Rf_mkString(exception_class.c_str()) : R_NilValue),
R_FindNamespace(Rf_mkString("Rcpp"))
) ;
}
void forward_exception_to_r( const std::exception& ex){
std::string exception_class ;
std::string exception_what = ex.what();
const char *name = typeid(ex).name() ;
// now we need to demangle "name"
{
int status = -1;
char *dem = 0;
dem = abi::__cxa_demangle(name, 0, 0, &status);
if( status == 0){
exception_class = dem ; /* great we can use the demangled name */
free(dem);
} else{
exception_class = name ; /* just using the mangled name */
}
}
Rf_eval(
Rf_lang3(
Rf_install("cpp_exception"),
Rf_mkString(exception_what.c_str()),
Rf_mkString(exception_class.c_str())
), R_FindNamespace(Rf_mkString("Rcpp"))
) ;
}
#else
void forward_uncaught_exceptions_to_r(){
Rf_eval(
Rf_lang3(
Rf_install("cpp_exception"),
Rf_mkString("exception : we don't know how to get the exception message with your compiler, patches welcome"),
R_NilValue),
R_FindNamespace(Rf_mkString("Rcpp"))
) ;
}
void forward_exception_to_r( const std::exception& ex){
Rf_eval(
Rf_lang3(
Rf_install("cpp_exception"),
Rf_mkString(ex.what()),
R_NilValue),
R_FindNamespace(Rf_mkString("Rcpp"))
) ;
}
std::string demangle( const std::string& name ){
return name ;
}
#endif
SEXP initUncaughtExceptionHandler(){
/* FIXME: we might want to restore the original handler as the package
gets unloaded */
std::set_terminate(forward_uncaught_exceptions_to_r);
return R_NilValue ;
}
Computing file changes ...