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

newmat11b
Generated Tue Nov 23 16:35:39 2004 by Doxygen 1.3.9.1