00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "w_defines.h"
00054
00055
00056
00057 #ifdef __GNUC__
00058 #pragma implementation "w_error.h"
00059 #endif
00060
00061 #include <cstring>
00062
00063 #define W_SOURCE
00064 #include <w_base.h>
00065 const
00066 #include <fc_einfo_gen.h>
00067 #if USE_BLOCK_ALLOC_FOR_W_ERROR_T
00068 #include "block_alloc.h"
00069 #endif
00070
00071
00072
00073
00074 const
00075 w_error_t::info_t* w_error_t::_range_start[w_error_t::max_range] = {
00076 w_error_t::error_info, 0
00077 };
00078 w_base_t::uint4_t w_error_t::_range_cnt[w_error_t::max_range] = {
00079 fcERRMAX - fcERRMIN + 1, 0
00080 };
00081
00082 const char *w_error_t::_range_name[w_error_t::max_range]= {
00083 "Foundation Classes",
00084 0
00085 };
00086 w_base_t::uint4_t w_error_t::_nreg = 1;
00087
00088
00089 const w_error_t w_error_t::no_error_instance(__FILE__, __LINE__, 0, 0, 0);
00090 w_error_t* const w_error_t::no_error = const_cast<w_error_t *>(&no_error_instance);
00091
00092 static void w_error_t_no_error_code()
00093 {
00094 }
00095
00096 #if W_DEBUG_LEVEL > 3
00097 #define CHECKIT do {\
00098 w_error_t* my = _next; \
00099 w_error_t* p = my; \
00100 while(p) { \
00101 if (p == p->_next || my == p->_next) { \
00102 cerr << "Recursive error detected:" << endl << *this << endl;\
00103 W_FATAL(fcINTERNAL); \
00104 } \
00105 p = p->_next; \
00106 } \
00107 } while(0)
00108
00109 #else
00110 #define CHECKIT
00111 #endif
00112
00113 w_error_t&
00114 w_error_t::add_trace_info(
00115 const char* const filename,
00116 uint4_t line_num)
00117 {
00118 verify_owner();
00119 if (_trace_cnt < max_trace) {
00120 _trace_file[_trace_cnt] = filename;
00121 _trace_line[_trace_cnt] = line_num;
00122 ++_trace_cnt;
00123 }
00124
00125 return *this;
00126 }
00127
00128 #if W_DEBUG_LEVEL > 1
00129 #define CHECK_STRING(x) if((x) != NULL) w_assert2(*(x) != 0)
00130 #else
00131 #define CHECK_STRING(x)
00132 #endif
00133
00134 w_error_t&
00135 w_error_t::clear_more_info_msg()
00136 {
00137 delete[] more_info_msg;
00138 more_info_msg = NULL;
00139 return *this;
00140 }
00141
00142 w_error_t&
00143 w_error_t::append_more_info_msg(const char* more_info)
00144 {
00145 CHECK_STRING(more_info);
00146 verify_owner();
00147 if (more_info)
00148 {
00149 int more_info_len = strlen(more_info);
00150 if(more_info_len > 0)
00151 {
00152 if(more_info[more_info_len-1] == '\n') more_info_len--;
00153
00154 int more_info_msg_len = more_info_msg?strlen(more_info_msg):0;
00155 char* new_more_info_msg = new
00156 char[more_info_len + more_info_msg_len + 2];
00157 if(more_info_msg) {
00158 strcpy(new_more_info_msg, more_info_msg);
00159 }
00160 strcpy(new_more_info_msg + more_info_msg_len, more_info);
00161 new_more_info_msg[more_info_msg_len + more_info_len] = '\n';
00162 new_more_info_msg[more_info_msg_len + more_info_len + 1] = '\0';
00163
00164 if(more_info_msg) delete[] more_info_msg;
00165 more_info_msg = new_more_info_msg;
00166
00167 CHECK_STRING(more_info_msg);
00168 }
00169 }
00170
00171 return *this;
00172 }
00173
00174 const char*
00175 w_error_t::get_more_info_msg() const
00176 {
00177 CHECK_STRING(more_info_msg);
00178 return more_info_msg;
00179 }
00180
00181
00182 inline w_base_t::uint4_t w_error_t::classify(int er)
00183 {
00184 uint4_t sys = 0;
00185 switch (er) {
00186 case fcOS:
00187 sys = errno;
00188 break;
00189 }
00190 return sys;
00191 }
00192
00193 #if USE_BLOCK_ALLOC_FOR_W_ERROR_T
00194 DEFINE_TLS_SWATCHZ(block_alloc<w_error_t>, w_error_alloc);
00195 void w_error_t::operator delete(void* p) {
00196 block_alloc<w_error_t>::destroy_object((w_error_t*) p);
00197 }
00198 #endif
00199
00200
00201 inline
00202 w_error_t::w_error_t(const char* const fi,
00203 uint4_t li,
00204 err_num_t er,
00205 w_error_t* list,
00206 const char* more_info)
00207 : err_num(er),
00208 file(fi),
00209 line(li),
00210 sys_err_num(classify(er)),
00211 more_info_msg(more_info),
00212 _trace_cnt(0),
00213 _next(list)
00214 {
00215 CHECK_STRING(more_info_msg);
00216 claim();
00217 CHECKIT;
00218 }
00219
00220
00221 w_error_t*
00222 w_error_t::make(
00223 const char* const filename,
00224 uint4_t line_num,
00225 err_num_t err_num,
00226 w_error_t* list,
00227 const char* more_info)
00228 {
00229 #if USE_BLOCK_ALLOC_FOR_W_ERROR_T
00230 return new (*w_error_alloc) w_error_t(filename, line_num, err_num, list, more_info);
00231 #else
00232 return new w_error_t(filename, line_num, err_num, list, more_info);
00233 #endif
00234
00235 }
00236
00237 inline NORET
00238 w_error_t::w_error_t(
00239 const char* const fi,
00240 uint4_t li,
00241 err_num_t er,
00242 uint4_t sys_er,
00243 w_error_t* list,
00244 const char* more_info)
00245 : err_num(er),
00246 file(fi), line(li),
00247 sys_err_num(sys_er),
00248 more_info_msg(more_info),
00249 _trace_cnt(0),
00250 _next(list)
00251 {
00252 CHECK_STRING(more_info_msg);
00253 claim();
00254 CHECKIT;
00255 }
00256
00257 w_error_t*
00258 w_error_t::make(
00259 const char* const filename,
00260 uint4_t line_num,
00261 err_num_t err_num,
00262 uint4_t sys_err,
00263 w_error_t* list,
00264 const char* more_info)
00265 {
00266 CHECK_STRING(more_info);
00267
00268 #if USE_BLOCK_ALLOC_FOR_W_ERROR_T
00269 return new (*w_error_alloc) w_error_t(filename, line_num,
00270 err_num, sys_err, list, more_info);
00271
00272
00273 #else
00274 return new w_error_t(filename, line_num, err_num, sys_err, list, more_info);
00275 #endif
00276 }
00277
00278
00279
00280
00281
00282 bool
00283 w_error_t::insert(
00284 const char * modulename,
00285 const info_t info[],
00286 uint4_t count)
00287 {
00288 if (_nreg >= max_range)
00289 return false;
00290
00291 err_num_t start = info[0].err_num;
00292
00293 for (uint4_t i = 0; i < _nreg; i++) {
00294 if (start >= _range_start[i]->err_num && start < _range_cnt[i])
00295 return false;
00296 uint4_t end = start + count;
00297 if (end >= _range_start[i]->err_num && end < _range_cnt[i])
00298 return false;
00299 }
00300 _range_start[_nreg] = info;
00301 _range_cnt[_nreg] = count;
00302 _range_name[_nreg] = modulename;
00303
00304 ++_nreg;
00305 return true;
00306 }
00307
00308 const char*
00309 w_error_t::error_string(err_num_t err_num)
00310 {
00311 if(err_num == w_error_t::no_error->err_num ) {
00312 return "no error";
00313 }
00314 uint4_t i;
00315 for (i = 0; i < _nreg; i++) {
00316 if (err_num >= _range_start[i]->err_num &&
00317 err_num <= _range_start[i]->err_num + _range_cnt[i]) {
00318 break;
00319 }
00320 }
00321
00322 if (i == _nreg) {
00323 w_error_t_no_error_code();
00324 return error_string( fcNOSUCHERROR );
00325
00326 }
00327
00328 const uint4_t j = CAST(int, err_num - _range_start[i]->err_num);
00329 return _range_start[i][j].errstr;
00330 }
00331
00332 const char*
00333 w_error_t::module_name(err_num_t err_num)
00334 {
00335 if(err_num == w_error_t::no_error->err_num ) {
00336 return "all modules";
00337 }
00338 uint4_t i;
00339 for (i = 0; i < _nreg; i++) {
00340 if (err_num >= _range_start[i]->err_num &&
00341 err_num <= _range_start[i]->err_num + _range_cnt[i]) {
00342 break;
00343 }
00344 }
00345
00346 if (i == _nreg) {
00347 return "unknown module";
00348 }
00349 return _range_name[i];
00350 }
00351
00352 void format_unix_error(int err, char *buf, int bufsize)
00353 {
00354 #ifdef HAVE_STRERROR
00355 char *s = strerror(err);
00356 #else
00357 char *s = "No strerror function. Cannot format unix error.";
00358 #endif
00359 strncpy(buf, s, bufsize);
00360 buf[bufsize-1] = '\0';
00361 }
00362
00363 ostream& w_error_t::print_error(ostream &o) const
00364 {
00365 if (this == w_error_t::no_error) {
00366 return o << "no error";
00367 }
00368
00369 int cnt = 1;
00370 for (const w_error_t* p = this; p; p = p->_next, ++cnt) {
00371
00372 const char* f = strrchr(p->file, '/');
00373 f ? ++f : f = p->file;
00374 o << cnt << ". error in " << f << ':' << p->line << " ";
00375 if(cnt > 1) {
00376 if(p == this) {
00377 o << "Error recurses, stopping" << endl;
00378 break;
00379 }
00380 if(p->_next == p) {
00381 o << "Error next is same, stopping" << endl;
00382 break;
00383 }
00384 }
00385 if(cnt > 20) {
00386 o << "Error chain >20, stopping" << endl;
00387 break;
00388 }
00389 o << p->error_string(p->err_num);
00390 o << " [0x" << hex << p->err_num << dec << "]";
00391
00392
00393
00394 switch (p->err_num) {
00395 case fcOS: {
00396 char buf[1024];
00397 format_unix_error(p->sys_err_num, buf, sizeof(buf));
00398 o << " --- " << buf;
00399 break;
00400 }
00401 }
00402
00403 o << endl;
00404
00405 if (more_info_msg) {
00406 o << "\tadditional information: " << more_info_msg << endl;
00407 }
00408
00409 if (p->_trace_cnt) {
00410 o << "\tcalled from:" << endl;
00411 for (unsigned i = 0; i < p->_trace_cnt; i++) {
00412 f = strrchr(p->_trace_file[i], '/');
00413 f ? ++f : f = p->_trace_file[i];
00414 o << "\t" << i << ") " << f << ':'
00415 << p->_trace_line[i] << endl;
00416 }
00417 }
00418 }
00419
00420 return o;
00421 }
00422
00423 ostream &operator<<(ostream &o, const w_error_t &obj)
00424 {
00425 return obj.print_error(o);
00426 }
00427
00428 ostream &
00429 w_error_t::print(ostream &out)
00430 {
00431 for (unsigned i = 0; i < _nreg; i++) {
00432 err_num_t first = _range_start[i]->err_num;
00433 unsigned int last = first + _range_cnt[i] - 1;
00434
00435 for (unsigned j = first; j <= last; j++) {
00436 const char *c = module_name(j);
00437 const char *s = error_string(j);
00438
00439 out << c << ":" << j << ":" << s << endl;
00440 }
00441 }
00442
00443 return out;
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607