rvm 1.08
|
00001 #include "config.h" 00002 00003 #include <cerrno> 00004 #include <cstring> 00005 #ifdef HAVE_CSTDIO 00006 #include <cstdio> 00007 #endif 00008 #ifdef HAVE_CSTDLIB 00009 #include <cstdlib> 00010 #endif 00011 00012 #include "asserts.h" 00013 #include "types.h" 00014 #include "error.h" 00015 00016 #define internal_TRY_nomem(code) \ 00017 try { \ 00018 code; \ 00019 } \ 00020 catch(...) { \ 00021 if (errno == 12) \ 00022 std::cerr << err_nomem; \ 00023 else \ 00024 std::cerr << err_unknown; \ 00025 } 00026 00027 //----------------------------------------------------------------------------- 00028 00029 error_instance::error_instance() 00030 { 00031 clear(); 00032 } 00033 00034 error_instance::error_instance(const error_instance& a_e) 00035 { 00036 set(a_e); 00037 } 00038 00039 error_instance::error_instance( 00040 const std::string a_what, 00041 #ifdef __GNUC__ 00042 const std::string a_where, 00043 #endif 00044 const std::string a_file, 00045 const uint16 a_line 00046 ) 00047 { 00048 set( 00049 a_what, 00050 #ifdef __GNUC__ 00051 a_where, 00052 #endif 00053 a_file, 00054 a_line 00055 ); 00056 } 00057 00058 void error_instance::clear(void) 00059 { 00060 internal_TRY_nomem(m_what = ""); 00061 #ifdef __GNUC__ 00062 internal_TRY_nomem(m_where = ""); 00063 #endif 00064 internal_TRY_nomem(m_file = ""); 00065 m_line = 0; 00066 } 00067 00068 void error_instance::set(void) 00069 { 00070 clear(); 00071 } 00072 00073 void error_instance::set( 00074 const std::string a_what, 00075 #ifdef __GNUC__ 00076 const std::string a_where, 00077 #endif 00078 const std::string a_file, 00079 const uint16 a_line 00080 ) 00081 { 00082 clear(); 00083 00084 internal_TRY_nomem(m_what = a_what); 00085 #ifdef __GNUC__ 00086 internal_TRY_nomem(m_where = a_where); 00087 #endif 00088 internal_TRY_nomem(m_file = a_file); 00089 m_line = a_line; 00090 } 00091 00092 void error_instance::set(const error_instance& a_e) 00093 { 00094 clear(); 00095 00096 internal_TRY_nomem(m_what = a_e.what()); 00097 #ifdef __GNUC__ 00098 internal_TRY_nomem(m_where = a_e.where()); 00099 #endif 00100 internal_TRY_nomem(m_file = a_e.file()); 00101 m_line = a_e.line(); 00102 } 00103 00104 const std::string error_instance::what(void) const 00105 { 00106 return(m_what); 00107 } 00108 00109 #ifdef __GNUC__ 00110 const std::string error_instance::where(void) const 00111 { 00112 return(m_where); 00113 } 00114 #endif 00115 00116 const std::string error_instance::file(void) const 00117 { 00118 return(m_file); 00119 } 00120 00121 const uint16 error_instance::line(void) const 00122 { 00123 return(m_line); 00124 } 00125 00126 error_instance& error_instance::operator=(const error_instance& a_e) 00127 { 00128 set(a_e); 00129 00130 return(*this); 00131 } 00132 00133 /* 00134 void 00135 error_instance::dump(std::ostream& a_out, const std::string& a_prefix) const 00136 { 00137 a_out 00138 << a_prefix 00139 << "error_instance::what = \"" 00140 << m_what 00141 << "\"" 00142 << std::endl; 00143 #ifdef __GNUC__ 00144 a_out 00145 << a_prefix 00146 << " ::where = " 00147 << m_where 00148 << std::endl; 00149 #endif 00150 a_out 00151 << a_prefix 00152 << " ::at " 00153 << m_file << "[" << m_line << "]" 00154 << std::endl; 00155 } 00156 */ 00157 00158 //----------------------------------------------------------------------------- 00159 00160 error::error(const int a_errno) 00161 { 00162 clear(); 00163 num(a_errno); 00164 } 00165 00166 error::error( 00167 const int a_errno, 00168 const error_instance& a_e, 00169 const bool a_internal 00170 ) 00171 { 00172 clear(); 00173 push_back(a_e); 00174 internal(a_internal); 00175 num(a_errno); 00176 } 00177 00178 error::error(const error& a_e) 00179 { 00180 assign(a_e); 00181 } 00182 00183 void error::clear(void) 00184 { 00185 m_errno = 0; 00186 m_internal = false; 00187 clear_stack(); 00188 } 00189 00190 void error::clear_stack(void) 00191 { 00192 type::clear(); 00193 } 00194 00195 void error::internal(bool a_i) 00196 { 00197 m_internal = a_i; 00198 } 00199 00200 const bool error::internal(void) const 00201 { 00202 return(m_internal); 00203 } 00204 00205 void error::num(int a_i) 00206 { 00207 m_errno = a_i; 00208 } 00209 00210 int error::num(void) const 00211 { 00212 return(m_errno); 00213 } 00214 00215 void error::push_back(const error_instance& a_e) 00216 { 00217 try { 00218 type::push_back(a_e); 00219 } 00220 catch(...) { 00221 std::cerr << "*** ERROR: "; 00222 if (errno != 0) { 00223 std::cerr 00224 << "[" << errno << "]: " 00225 << get_error_str(errno) 00226 << std::endl; 00227 std::cerr << " "; 00228 errno = 0; 00229 } 00230 std::cerr << "error::push_back() failed" << std::endl; 00231 } 00232 } 00233 00234 void error::push_back(const error& a_e) 00235 { 00236 error::const_iterator ei; 00237 00238 for (ei = a_e.begin(); ei != a_e.end(); ei++) { 00239 push_back(*ei); 00240 } 00241 } 00242 00243 void error::push_back(const std::string& a_str) 00244 { 00245 error_instance ei; 00246 00247 internal_TRY_nomem(ei = ERROR_INSTANCE(a_str)); 00248 push_back(ei); 00249 } 00250 00251 void error::assign(const error& a_e) 00252 { 00253 const_iterator eii; 00254 00255 clear(); 00256 m_errno = a_e.num(); 00257 m_internal = a_e.internal(); 00258 for (eii = a_e.begin(); eii != a_e.end(); eii++) { 00259 push_back(*eii); 00260 } 00261 } 00262 00263 error& error::operator=(const error& a_e) 00264 { 00265 assign(a_e); 00266 00267 return(*this); 00268 } 00269 00270 std::ostream& 00271 error::write(std::ostream& a_out, const std::string a_prefix) const 00272 { 00273 const_iterator eii; 00274 00275 if (a_prefix.size() != 0) 00276 a_out << a_prefix << " "; 00277 a_out << "*** "; 00278 if (m_internal) 00279 a_out << "INTERNAL "; 00280 a_out << "ERROR"; 00281 00282 if (m_errno != 0) 00283 a_out << " [" << m_errno << "]: " << strerror(m_errno); 00284 a_out << std::endl; 00285 00286 for (eii = begin(); eii != end(); ++eii) { 00287 if (a_prefix.size() != 0) 00288 a_out << a_prefix << " "; 00289 if (eii->what().size() != 0) 00290 a_out << " " << eii->what() << std::endl; 00291 if (m_internal) { 00292 a_out << " "; 00293 #ifdef __GNUC__ 00294 a_out << "in " << eii->where() << " "; 00295 #endif 00296 a_out << "at " << eii->file() << "[" << eii->line() << "]"; 00297 a_out << std::endl; 00298 } 00299 } 00300 00301 return(a_out); 00302 } 00303 00304 const std::string error::str(const std::string a_prefix) const 00305 { 00306 static const size_t buffer_len = 32; 00307 char buffer[buffer_len] = { 0 }; 00308 std::string es; 00309 const_iterator eii; 00310 00311 try { 00312 es.erase(); 00313 if (a_prefix.size() != 0) { 00314 es += a_prefix; 00315 es += " "; 00316 } 00317 es += "*** "; 00318 if (m_internal) 00319 es += "INTERNAL "; 00320 es += "ERROR"; 00321 00322 snprintf(buffer, buffer_len, "%d", m_errno); 00323 if (m_errno != 0) { 00324 es += " ["; 00325 es += buffer; 00326 es += "]: "; 00327 es += strerror(m_errno); 00328 } 00329 es += "\n"; 00330 00331 for (eii = begin(); eii != end(); ++eii) { 00332 if (a_prefix.size() != 0) 00333 es += a_prefix + " "; 00334 if (eii->what().size() != 0) { 00335 es += " "; 00336 es += eii->what(); 00337 es += "\n"; 00338 } 00339 snprintf(buffer, buffer_len, "%u", eii->line()); 00340 if (m_internal) { 00341 es += " "; 00342 #ifdef __GNUC__ 00343 es += "in "; 00344 es += eii->where(); 00345 es += " "; 00346 #endif 00347 es += "at "; 00348 es += eii->file(); 00349 es += "["; 00350 es += buffer; 00351 es += "]"; 00352 es += "\n"; 00353 } 00354 } 00355 } 00356 catch(...) { 00357 if (errno == 12) 00358 std::cerr << err_nomem; 00359 else 00360 std::cerr << err_unknown; 00361 } 00362 00363 return(es); 00364 } 00365 00366 /* 00367 std::ostream& error::dump(std::ostream& a_out) const 00368 { 00369 const_iterator eii; 00370 00371 a_out << "ERROR: errno = " << m_errno; 00372 if (m_errno != 0) { 00373 a_out << " \"" << strerror(m_errno) << "\""; 00374 } 00375 a_out << std::endl; 00376 for (eii = begin(); eii != end(); ++eii) { 00377 eii->dump(a_out, " "); 00378 } 00379 00380 return(a_out); 00381 } 00382 */ 00383 00384 std::ostream& operator<<(std::ostream& a_out, const error& a_e) 00385 { 00386 return(a_e.write(a_out)); 00387 } 00388 00389 const char * get_error_str(const int a_err) 00390 { 00391 return(strerror(a_err)); 00392 } 00393 00394 //----------------------------------------------------------------------------- 00395