Virtual U.org
Get Personal Training on VU Today
    
Top shadow
 
 register/help
User Name:

Password:

MYEXCEPT.CPP Source File
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

MYEXCEPT.CPP

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

Generated on Fri Aug 23 01:37:02 2002 for VirtualU by doxygen1.2.17