#include "config.h" #include #include #ifdef HAVE_CSTDIO #include #endif #ifdef HAVE_CSTDLIB #include #endif #include "asserts.h" #include "types.h" #include "error.h" #define internal_TRY_nomem(code) \ try { \ code; \ } \ catch(...) { \ if (errno == 12) \ std::cerr << err_nomem; \ else \ std::cerr << err_unknown; \ } //----------------------------------------------------------------------------- error_instance::error_instance() { clear(); } error_instance::error_instance(const error_instance& a_e) { set(a_e); } error_instance::error_instance( const std::string a_what, #ifdef __GNUC__ const std::string a_where, #endif const std::string a_file, const uint16 a_line ) { set( a_what, #ifdef __GNUC__ a_where, #endif a_file, a_line ); } void error_instance::clear(void) { internal_TRY_nomem(m_what = ""); #ifdef __GNUC__ internal_TRY_nomem(m_where = ""); #endif internal_TRY_nomem(m_file = ""); m_line = 0; } void error_instance::set(void) { clear(); } void error_instance::set( const std::string a_what, #ifdef __GNUC__ const std::string a_where, #endif const std::string a_file, const uint16 a_line ) { clear(); internal_TRY_nomem(m_what = a_what); #ifdef __GNUC__ internal_TRY_nomem(m_where = a_where); #endif internal_TRY_nomem(m_file = a_file); m_line = a_line; } void error_instance::set(const error_instance& a_e) { clear(); internal_TRY_nomem(m_what = a_e.what()); #ifdef __GNUC__ internal_TRY_nomem(m_where = a_e.where()); #endif internal_TRY_nomem(m_file = a_e.file()); m_line = a_e.line(); } const std::string error_instance::what(void) const { return(m_what); } #ifdef __GNUC__ const std::string error_instance::where(void) const { return(m_where); } #endif const std::string error_instance::file(void) const { return(m_file); } const uint16 error_instance::line(void) const { return(m_line); } error_instance& error_instance::operator=(const error_instance& a_e) { set(a_e); return(*this); } /* void error_instance::dump(std::ostream& a_out, const std::string& a_prefix) const { a_out << a_prefix << "error_instance::what = \"" << m_what << "\"" << std::endl; #ifdef __GNUC__ a_out << a_prefix << " ::where = " << m_where << std::endl; #endif a_out << a_prefix << " ::at " << m_file << "[" << m_line << "]" << std::endl; } */ //----------------------------------------------------------------------------- error::error(const int a_errno) { clear(); num(a_errno); } error::error( const int a_errno, const error_instance& a_e, const bool a_internal ) { clear(); push_back(a_e); internal(a_internal); num(a_errno); } error::error(const error& a_e) { assign(a_e); } void error::clear(void) { m_errno = 0; m_internal = false; clear_stack(); } void error::clear_stack(void) { type::clear(); } void error::internal(bool a_i) { m_internal = a_i; } const bool error::internal(void) const { return(m_internal); } void error::num(int a_i) { m_errno = a_i; } int error::num(void) const { return(m_errno); } void error::push_back(const error_instance& a_e) { try { type::push_back(a_e); } catch(...) { std::cerr << "*** ERROR: "; if (errno != 0) { std::cerr << "[" << errno << "]: " << get_error_str(errno) << std::endl; std::cerr << " "; errno = 0; } std::cerr << "error::push_back() failed" << std::endl; } } void error::push_back(const error& a_e) { error::const_iterator ei; for (ei = a_e.begin(); ei != a_e.end(); ei++) { push_back(*ei); } } void error::push_back(const std::string& a_str) { error_instance ei; internal_TRY_nomem(ei = ERROR_INSTANCE(a_str)); push_back(ei); } void error::assign(const error& a_e) { const_iterator eii; clear(); m_errno = a_e.num(); m_internal = a_e.internal(); for (eii = a_e.begin(); eii != a_e.end(); eii++) { push_back(*eii); } } error& error::operator=(const error& a_e) { assign(a_e); return(*this); } std::ostream& error::write(std::ostream& a_out, const std::string a_prefix) const { const_iterator eii; if (a_prefix.size() != 0) a_out << a_prefix << " "; a_out << "*** "; if (m_internal) a_out << "INTERNAL "; a_out << "ERROR"; if (m_errno != 0) a_out << " [" << m_errno << "]: " << strerror(m_errno); a_out << std::endl; for (eii = begin(); eii != end(); ++eii) { if (a_prefix.size() != 0) a_out << a_prefix << " "; if (eii->what().size() != 0) a_out << " " << eii->what() << std::endl; if (m_internal) { a_out << " "; #ifdef __GNUC__ a_out << "in " << eii->where() << " "; #endif a_out << "at " << eii->file() << "[" << eii->line() << "]"; a_out << std::endl; } } return(a_out); } const std::string error::str(const std::string a_prefix) const { static const size_t buffer_len = 32; char buffer[buffer_len] = { 0 }; std::string es; const_iterator eii; try { es.erase(); if (a_prefix.size() != 0) { es += a_prefix; es += " "; } es += "*** "; if (m_internal) es += "INTERNAL "; es += "ERROR"; snprintf(buffer, buffer_len, "%d", m_errno); if (m_errno != 0) { es += " ["; es += buffer; es += "]: "; es += strerror(m_errno); } es += "\n"; for (eii = begin(); eii != end(); ++eii) { if (a_prefix.size() != 0) es += a_prefix + " "; if (eii->what().size() != 0) { es += " "; es += eii->what(); es += "\n"; } snprintf(buffer, buffer_len, "%u", eii->line()); if (m_internal) { es += " "; #ifdef __GNUC__ es += "in "; es += eii->where(); es += " "; #endif es += "at "; es += eii->file(); es += "["; es += buffer; es += "]"; es += "\n"; } } } catch(...) { if (errno == 12) std::cerr << err_nomem; else std::cerr << err_unknown; } return(es); } /* std::ostream& error::dump(std::ostream& a_out) const { const_iterator eii; a_out << "ERROR: errno = " << m_errno; if (m_errno != 0) { a_out << " \"" << strerror(m_errno) << "\""; } a_out << std::endl; for (eii = begin(); eii != end(); ++eii) { eii->dump(a_out, " "); } return(a_out); } */ std::ostream& operator<<(std::ostream& a_out, const error& a_e) { return(a_e.write(a_out)); } const char * get_error_str(const int a_err) { return(strerror(a_err)); } //-----------------------------------------------------------------------------