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
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
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
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
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