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