Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

myexcept.cpp

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

newmat11b
Generated Mon May 9 04:54:17 2016 by Doxygen 1.6.3