00001
00002
00003
00004
00005 #include "SdlArs.h"
00006
00007
00008
00009 #include <string.h>
00010
00011 #include "include.h"
00012
00013
00014 #include "myexcept.h"
00015
00016 #ifdef use_namespace
00017 namespace RBD_COMMON {
00018 #endif
00019
00020
00021
00022
00023
00024
00025 #ifdef SimulateExceptions
00026
00027 void Throw()
00028 {
00029 for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor)
00030 jan->CleanUp();
00031 JumpItem* jx = JumpBase::jl->ji;
00032 if ( !jx ) { Terminate(); }
00033 JumpBase::jl = jx;
00034
00035 Tracer::last = JumpBase::jl->trace;
00036 longjmp(JumpBase::jl->env, 1);
00037 }
00038
00039 #endif // end of simulate exceptions
00040
00041
00042 unsigned long Exception::Select;
00043 char* Exception::what_error;
00044 int Exception::SoFar;
00045 int Exception::LastOne;
00046
00047 Exception::Exception(const char* a_what)
00048 {
00049 Select++; SoFar = 0;
00050 if (!what_error)
00051 {
00052 LastOne = 511;
00053 what_error = new char[512];
00054 if (!what_error)
00055 {
00056 LastOne = 0;
00057 what_error = "No heap space for exception message\n";
00058 }
00059 }
00060 AddMessage("\n\nAn exception has been thrown\n");
00061 AddMessage(a_what);
00062 if (a_what) Tracer::AddTrace();
00063 }
00064
00065 void Exception::AddMessage(const char* a_what)
00066 {
00067 if (a_what)
00068 {
00069 int l = strlen(a_what); int r = LastOne - SoFar;
00070 if (l < r) { strcpy(what_error+SoFar, a_what); SoFar += l; }
00071 else if (r > 0)
00072 {
00073 strncpy(what_error+SoFar, a_what, r);
00074 what_error[LastOne] = 0;
00075 SoFar = LastOne;
00076 }
00077 }
00078 }
00079
00080 void Exception::AddInt(int value)
00081 {
00082 bool negative;
00083 if (value == 0) { AddMessage("0"); return; }
00084 else if (value < 0) { value = -value; negative = true; }
00085 else negative = false;
00086 int n = 0; int v = value;
00087 while (v > 0) { v /= 10; n++; }
00088 if (negative) n++;
00089 if (LastOne-SoFar < n) { AddMessage("***"); return; }
00090
00091 SoFar += n; n = SoFar; what_error[n] = 0;
00092 while (value > 0)
00093 {
00094 int nv = value / 10; int rm = value - nv * 10; value = nv;
00095 what_error[--n] = (char)(rm + '0');
00096 }
00097 if (negative) what_error[--n] = '-';
00098 return;
00099 }
00100
00101 void Tracer::PrintTrace()
00102 {
00103
00104
00105
00106
00107
00108 }
00109
00110 void Tracer::AddTrace()
00111 {
00112 if (last)
00113 {
00114 Exception::AddMessage("Trace: ");
00115 Exception::AddMessage(last->entry);
00116 for (Tracer* et = last->previous; et; et=et->previous)
00117 {
00118 Exception::AddMessage("; ");
00119 Exception::AddMessage(et->entry);
00120 }
00121 Exception::AddMessage(".\n");
00122 }
00123 }
00124
00125 #ifdef SimulateExceptions
00126
00127
00128 Janitor::Janitor()
00129 {
00130 if (do_not_link)
00131 {
00132 do_not_link = false; NextJanitor = 0; OnStack = false;
00133 #ifdef CLEAN_LIST
00134 cout << "Not added to clean-list " << (unsigned long)this << "\n";
00135 #endif
00136 }
00137 else
00138 {
00139 OnStack = true;
00140 #ifdef CLEAN_LIST
00141 cout << "Add to clean-list " << (unsigned long)this << "\n";
00142 #endif
00143 NextJanitor = JumpBase::jl->janitor; JumpBase::jl->janitor=this;
00144 }
00145 }
00146
00147 Janitor::~Janitor()
00148 {
00149
00150
00151 if (OnStack)
00152 {
00153 #ifdef CLEAN_LIST
00154 cout << "Delete from clean-list " << (unsigned long)this << "\n";
00155 #endif
00156 Janitor* lastjan = JumpBase::jl->janitor;
00157 if (this == lastjan) JumpBase::jl->janitor = NextJanitor;
00158 else
00159 {
00160 for (Janitor* jan = lastjan->NextJanitor; jan;
00161 jan = lastjan->NextJanitor)
00162 {
00163 if (jan==this)
00164 { lastjan->NextJanitor = jan->NextJanitor; return; }
00165 lastjan=jan;
00166 }
00167
00168 Throw(Exception(
00169 "Cannot resolve memory linked list\nSee notes in myexcept.cpp for details\n"
00170 ));
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 }
00199 }
00200 }
00201
00202 JumpItem* JumpBase::jl;
00203 jmp_buf JumpBase::env;
00204 bool Janitor::do_not_link;
00205
00206
00207 int JanitorInitializer::ref_count;
00208
00209 JanitorInitializer::JanitorInitializer()
00210 {
00211 if (ref_count++ == 0) new JumpItem;
00212
00213 }
00214
00215 #endif // end of SimulateExceptions
00216
00217 Tracer* Tracer::last;
00218
00219
00220 void Terminate()
00221 {
00222
00223 const char* what = Exception::what();
00224
00225 exit(1);
00226 }
00227
00228
00229
00230 #ifdef DO_FREE_CHECK
00231
00232
00233 FreeCheckLink::FreeCheckLink() : next(FreeCheck::next)
00234 { FreeCheck::next = this; }
00235
00236 FCLClass::FCLClass(void* t, char* name) : ClassName(name) { ClassStore=t; }
00237
00238 FCLRealArray::FCLRealArray(void* t, char* o, int s)
00239 : Operation(o), size(s) { ClassStore=t; }
00240
00241 FCLIntArray::FCLIntArray(void* t, char* o, int s)
00242 : Operation(o), size(s) { ClassStore=t; }
00243
00244 FreeCheckLink* FreeCheck::next;
00245 int FreeCheck::BadDelete;
00246
00247 void FCLClass::Report()
00248 { cout << " " << ClassName << " " << (unsigned long)ClassStore << "\n"; }
00249
00250 void FCLRealArray::Report()
00251 {
00252 cout << " " << Operation << " " << (unsigned long)ClassStore <<
00253 " " << size << "\n";
00254 }
00255
00256 void FCLIntArray::Report()
00257 {
00258 cout << " " << Operation << " " << (unsigned long)ClassStore <<
00259 " " << size << "\n";
00260 }
00261
00262 void FreeCheck::Register(void* t, char* name)
00263 {
00264 FCLClass* f = new FCLClass(t,name);
00265 if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
00266 #ifdef REG_DEREG
00267 cout << "Registering " << name << " " << (unsigned long)t << "\n";
00268 #endif
00269 }
00270
00271 void FreeCheck::RegisterR(void* t, char* o, int s)
00272 {
00273 FCLRealArray* f = new FCLRealArray(t,o,s);
00274 if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
00275 #ifdef REG_DEREG
00276 cout << o << " " << s << " " << (unsigned long)t << "\n";
00277 #endif
00278 }
00279
00280 void FreeCheck::RegisterI(void* t, char* o, int s)
00281 {
00282 FCLIntArray* f = new FCLIntArray(t,o,s);
00283 if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
00284 #ifdef REG_DEREG
00285 cout << o << " " << s << " " << (unsigned long)t << "\n";
00286 #endif
00287 }
00288
00289 void FreeCheck::DeRegister(void* t, char* name)
00290 {
00291 FreeCheckLink* last = 0;
00292 #ifdef REG_DEREG
00293 cout << "Deregistering " << name << " " << (unsigned long)t << "\n";
00294 #endif
00295 for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
00296 {
00297 if (fcl->ClassStore==t)
00298 {
00299 if (last) last->next = fcl->next; else next = fcl->next;
00300 delete fcl; return;
00301 }
00302 last = fcl;
00303 }
00304 cout << "\nRequest to delete non-existent object of class and location:\n";
00305 cout << " " << name << " " << (unsigned long)t << "\n";
00306 BadDelete++;
00307 Tracer::PrintTrace();
00308 cout << "\n";
00309 }
00310
00311 void FreeCheck::DeRegisterR(void* t, char* o, int s)
00312 {
00313 FreeCheckLink* last = 0;
00314 #ifdef REG_DEREG
00315 cout << o << " " << s << " " << (unsigned long)t << "\n";
00316 #endif
00317 for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
00318 {
00319 if (fcl->ClassStore==t)
00320 {
00321 if (last) last->next = fcl->next; else next = fcl->next;
00322 if (s >= 0 && ((FCLRealArray*)fcl)->size != s)
00323 {
00324 cout << "\nArray sizes do not agree:\n";
00325 cout << " " << o << " " << (unsigned long)t
00326 << " " << ((FCLRealArray*)fcl)->size << " " << s << "\n";
00327 Tracer::PrintTrace();
00328 cout << "\n";
00329 }
00330 delete fcl; return;
00331 }
00332 last = fcl;
00333 }
00334 cout << "\nRequest to delete non-existent real array:\n";
00335 cout << " " << o << " " << (unsigned long)t << " " << s << "\n";
00336 BadDelete++;
00337 Tracer::PrintTrace();
00338 cout << "\n";
00339 }
00340
00341 void FreeCheck::DeRegisterI(void* t, char* o, int s)
00342 {
00343 FreeCheckLink* last = 0;
00344 #ifdef REG_DEREG
00345 cout << o << " " << s << " " << (unsigned long)t << "\n";
00346 #endif
00347 for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
00348 {
00349 if (fcl->ClassStore==t)
00350 {
00351 if (last) last->next = fcl->next; else next = fcl->next;
00352 if (s >= 0 && ((FCLIntArray*)fcl)->size != s)
00353 {
00354 cout << "\nArray sizes do not agree:\n";
00355 cout << " " << o << " " << (unsigned long)t
00356 << " " << ((FCLIntArray*)fcl)->size << " " << s << "\n";
00357 Tracer::PrintTrace();
00358 cout << "\n";
00359 }
00360 delete fcl; return;
00361 }
00362 last = fcl;
00363 }
00364 cout << "\nRequest to delete non-existent int array:\n";
00365 cout << " " << o << " " << (unsigned long)t << " " << s << "\n";
00366 BadDelete++;
00367 Tracer::PrintTrace();
00368 cout << "\n";
00369 }
00370
00371 void FreeCheck::Status()
00372 {
00373 if (next)
00374 {
00375 cout << "\nObjects of the following classes remain undeleted:\n";
00376 for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) fcl->Report();
00377 cout << "\n";
00378 }
00379 else cout << "\nNo objects remain undeleted\n\n";
00380 if (BadDelete)
00381 {
00382 cout << "\nThere were " << BadDelete <<
00383 " requests to delete non-existent items\n\n";
00384 }
00385 }
00386
00387 #endif // end of DO_FREE_CHECK
00388
00389
00390
00391 Logic_error::Logic_error(const char* a_what) : Exception()
00392 {
00393 Select = Exception::Select;
00394 AddMessage("Logic error:- "); AddMessage(a_what);
00395 if (a_what) Tracer::AddTrace();
00396 }
00397
00398 Runtime_error::Runtime_error(const char* a_what)
00399 : Exception()
00400 {
00401 Select = Exception::Select;
00402 AddMessage("Runtime error:- "); AddMessage(a_what);
00403 if (a_what) Tracer::AddTrace();
00404 }
00405
00406 Domain_error::Domain_error(const char* a_what) : Logic_error()
00407 {
00408 Select = Exception::Select;
00409 AddMessage("domain error\n"); AddMessage(a_what);
00410 if (a_what) Tracer::AddTrace();
00411 }
00412
00413 Invalid_argument::Invalid_argument(const char* a_what) : Logic_error()
00414 {
00415 Select = Exception::Select;
00416 AddMessage("invalid argument\n"); AddMessage(a_what);
00417 if (a_what) Tracer::AddTrace();
00418 }
00419
00420 Length_error::Length_error(const char* a_what) : Logic_error()
00421 {
00422 Select = Exception::Select;
00423 AddMessage("length error\n"); AddMessage(a_what);
00424 if (a_what) Tracer::AddTrace();
00425 }
00426
00427 Out_of_range::Out_of_range(const char* a_what) : Logic_error()
00428 {
00429 Select = Exception::Select;
00430 AddMessage("out of range\n"); AddMessage(a_what);
00431 if (a_what) Tracer::AddTrace();
00432 }
00433
00434 Bad_cast::Bad_cast(const char* a_what) : Logic_error()
00435 {
00436 Select = Exception::Select;
00437 AddMessage("bad cast\n"); AddMessage(a_what);
00438 if (a_what) Tracer::AddTrace();
00439 }
00440
00441 Bad_typeid::Bad_typeid(const char* a_what) : Logic_error()
00442 {
00443 Select = Exception::Select;
00444 AddMessage("bad type id.\n"); AddMessage(a_what);
00445 if (a_what) Tracer::AddTrace();
00446 }
00447
00448 Range_error::Range_error(const char* a_what) : Runtime_error()
00449 {
00450 Select = Exception::Select;
00451 AddMessage("range error\n"); AddMessage(a_what);
00452 if (a_what) Tracer::AddTrace();
00453 }
00454
00455 Overflow_error::Overflow_error(const char* a_what) : Runtime_error()
00456 {
00457 Select = Exception::Select;
00458 AddMessage("overflow error\n"); AddMessage(a_what);
00459 if (a_what) Tracer::AddTrace();
00460 }
00461
00462 Bad_alloc::Bad_alloc(const char* a_what) : Exception()
00463 {
00464 Select = Exception::Select;
00465 AddMessage("bad allocation\n"); AddMessage(a_what);
00466 if (a_what) Tracer::AddTrace();
00467 }
00468
00469
00470
00471
00472 unsigned long Logic_error::Select;
00473 unsigned long Runtime_error::Select;
00474 unsigned long Domain_error::Select;
00475 unsigned long Invalid_argument::Select;
00476 unsigned long Length_error::Select;
00477 unsigned long Out_of_range::Select;
00478 unsigned long Bad_cast::Select;
00479 unsigned long Bad_typeid::Select;
00480 unsigned long Range_error::Select;
00481 unsigned long Overflow_error::Select;
00482 unsigned long Bad_alloc::Select;
00483
00484 #ifdef use_namespace
00485 }
00486 #endif
00487
00488