$search
00001 00002 00003 00012 00013 00014 // A set of classes to simulate exceptions in C++ 00015 // 00016 // Partially copied from Carlos Vidal s article in the C users journal 00017 // September 1992, pp 19-28 00018 // 00019 // Operations defined 00020 // Try { } 00021 // Throw ( exception object ) 00022 // ReThrow 00023 // Catch ( exception class ) { } 00024 // CatchAll { } 00025 // CatchAndThrow 00026 // 00027 // All catch lists must end with a CatchAll or CatchAndThrow statement 00028 // but not both. 00029 // 00030 // When exceptions are finally implemented replace Try, Throw(E), Rethrow, 00031 // Catch, CatchAll, CatchAndThrow by try, throw E, throw, catch, 00032 // catch(...), and {}. 00033 // 00034 // All exception classes must be derived from BaseException, have no 00035 // non-static variables and must include the statement 00036 // 00037 // static unsigned long Select; 00038 // 00039 // Any constructor in one of these exception classes must include 00040 // 00041 // Select = BaseException::Select; 00042 // 00043 // For each exceptions class, EX_1, some .cpp file must include 00044 // 00045 // unsigned long EX_1::Select; 00046 // 00047 00048 00049 #ifndef EXCEPTION_LIB 00050 #define EXCEPTION_LIB 00051 00052 #include "include.h" 00053 00054 #ifdef use_namespace 00055 namespace RBD_COMMON { 00056 #endif 00057 00058 00059 void Terminate(); 00060 00061 00062 //********** classes for setting up exceptions and reporting ************// 00063 00064 class BaseException; 00065 00066 class Tracer // linked list showing how 00067 { // we got here 00068 const char* entry; 00069 Tracer* previous; 00070 public: 00071 Tracer(const char*); 00072 ~Tracer(); 00073 void ReName(const char*); 00074 static void PrintTrace(); // for printing trace 00075 static void AddTrace(); // insert trace in exception record 00076 static Tracer* last; // points to Tracer list 00077 friend class BaseException; 00078 }; 00079 00080 00081 class BaseException // The base exception class 00082 { 00083 protected: 00084 static char* what_error; // error message 00085 static int SoFar; // no. characters already entered 00086 static int LastOne; // last location in error buffer 00087 public: 00088 static void AddMessage(const char* a_what); 00089 // messages about exception 00090 static void AddInt(int value); // integer to error message 00091 static unsigned long Select; // for identifying exception 00092 BaseException(const char* a_what = 0); 00093 static const char* what() { return what_error; } 00094 // for getting error message 00095 }; 00096 00097 #ifdef TypeDefException 00098 typedef BaseException Exception; // for compatibility with my older libraries 00099 #endif 00100 00101 inline Tracer::Tracer(const char* e) 00102 : entry(e), previous(last) { last = this; } 00103 00104 inline Tracer::~Tracer() { last = previous; } 00105 00106 inline void Tracer::ReName(const char* e) { entry=e; } 00107 00108 #ifdef SimulateExceptions // SimulateExceptions 00109 00110 #include <setjmp.h> 00111 00112 00113 //************* the definitions of Try, Throw and Catch *****************// 00114 00115 00116 class JumpItem; 00117 class Janitor; 00118 00119 class JumpBase // pointer to a linked list of jmp_buf s 00120 { 00121 public: 00122 static JumpItem *jl; 00123 static jmp_buf env; 00124 }; 00125 00126 class JumpItem // an item in a linked list of jmp_buf s 00127 { 00128 public: 00129 JumpItem *ji; 00130 jmp_buf env; 00131 Tracer* trace; // to keep check on Tracer items 00132 Janitor* janitor; // list of items for cleanup 00133 JumpItem() : ji(JumpBase::jl), trace(0), janitor(0) 00134 { JumpBase::jl = this; } 00135 ~JumpItem() { JumpBase::jl = ji; } 00136 }; 00137 00138 void Throw(); 00139 00140 inline void Throw(const BaseException&) { Throw(); } 00141 00142 #define Try \ 00143 if (!setjmp( JumpBase::jl->env )) { \ 00144 JumpBase::jl->trace = Tracer::last; \ 00145 JumpItem JI387256156; 00146 00147 #define ReThrow Throw() 00148 00149 #define Catch(EXCEPTION) \ 00150 } else if (BaseException::Select == EXCEPTION::Select) { 00151 00152 #define CatchAll } else 00153 00154 #define CatchAndThrow } else Throw(); 00155 00156 00157 //****************** cleanup heap following Throw ***********************// 00158 00159 class Janitor 00160 { 00161 protected: 00162 static bool do_not_link; // set when new is called 00163 bool OnStack; // false if created by new 00164 public: 00165 Janitor* NextJanitor; 00166 virtual void CleanUp() {} 00167 Janitor(); 00168 virtual ~Janitor(); 00169 }; 00170 00171 00172 // The tiresome old trick for initializing the Janitor class 00173 // this is needed for classes derived from Janitor which have objects 00174 // declared globally 00175 00176 class JanitorInitializer 00177 { 00178 public: 00179 JanitorInitializer(); 00180 private: 00181 static int ref_count; 00182 }; 00183 00184 static JanitorInitializer JanInit; 00185 00186 #endif // end of SimulateExceptions 00187 00188 #ifdef UseExceptions 00189 00190 #define Try try 00191 #define Throw(E) throw E 00192 #define ReThrow throw 00193 #define Catch catch 00194 #define CatchAll catch(...) 00195 #define CatchAndThrow {} 00196 00197 #endif // end of UseExceptions 00198 00199 00200 #ifdef DisableExceptions // Disable exceptions 00201 00202 #define Try { 00203 #define ReThrow Throw() 00204 #define Catch(EXCEPTION) } if (false) { 00205 #define CatchAll } if (false) 00206 #define CatchAndThrow } 00207 00208 inline void Throw() { Terminate(); } 00209 inline void Throw(const BaseException&) { Terminate(); } 00210 00211 00212 #endif // end of DisableExceptions 00213 00214 #ifndef SimulateExceptions // ! SimulateExceptions 00215 00216 class Janitor // a dummy version 00217 { 00218 public: 00219 virtual void CleanUp() {} 00220 Janitor() {} 00221 virtual ~Janitor() {} 00222 }; 00223 00224 #endif // end of ! SimulateExceptions 00225 00226 00227 //******************** FREE_CHECK and NEW_DELETE ***********************// 00228 00229 #ifdef DO_FREE_CHECK // DO_FREE_CHECK 00230 // Routines for tracing whether new and delete calls are balanced 00231 00232 class FreeCheck; 00233 00234 class FreeCheckLink 00235 { 00236 protected: 00237 FreeCheckLink* next; 00238 void* ClassStore; 00239 FreeCheckLink(); 00240 virtual void Report()=0; // print details of link 00241 friend class FreeCheck; 00242 }; 00243 00244 class FCLClass : public FreeCheckLink // for registering objects 00245 { 00246 char* ClassName; 00247 FCLClass(void* t, char* name); 00248 void Report(); 00249 friend class FreeCheck; 00250 }; 00251 00252 class FCLRealArray : public FreeCheckLink // for registering real arrays 00253 { 00254 char* Operation; 00255 int size; 00256 FCLRealArray(void* t, char* o, int s); 00257 void Report(); 00258 friend class FreeCheck; 00259 }; 00260 00261 class FCLIntArray : public FreeCheckLink // for registering int arrays 00262 { 00263 char* Operation; 00264 int size; 00265 FCLIntArray(void* t, char* o, int s); 00266 void Report(); 00267 friend class FreeCheck; 00268 }; 00269 00270 00271 class FreeCheck 00272 { 00273 static FreeCheckLink* next; 00274 static int BadDelete; 00275 public: 00276 static void Register(void*, char*); 00277 static void DeRegister(void*, char*); 00278 static void RegisterR(void*, char*, int); 00279 static void DeRegisterR(void*, char*, int); 00280 static void RegisterI(void*, char*, int); 00281 static void DeRegisterI(void*, char*, int); 00282 static void Status(); 00283 friend class FreeCheckLink; 00284 friend class FCLClass; 00285 friend class FCLRealArray; 00286 friend class FCLIntArray; 00287 }; 00288 00289 #define FREE_CHECK(Class) \ 00290 public: \ 00291 void* operator new(size_t size) \ 00292 { \ 00293 void* t = ::operator new(size); FreeCheck::Register(t,#Class); \ 00294 return t; \ 00295 } \ 00296 void operator delete(void* t) \ 00297 { FreeCheck::DeRegister(t,#Class); ::operator delete(t); } 00298 00299 00300 #ifdef SimulateExceptions // SimulateExceptions 00301 00302 #define NEW_DELETE(Class) \ 00303 public: \ 00304 void* operator new(size_t size) \ 00305 { \ 00306 do_not_link=true; \ 00307 void* t = ::operator new(size); FreeCheck::Register(t,#Class); \ 00308 return t; \ 00309 } \ 00310 void operator delete(void* t) \ 00311 { FreeCheck::DeRegister(t,#Class); ::operator delete(t); } 00312 00313 00314 #endif // end of SimulateExceptions 00315 00316 00317 #define MONITOR_REAL_NEW(Operation, Size, Pointer) \ 00318 FreeCheck::RegisterR(Pointer, Operation, Size); 00319 #define MONITOR_INT_NEW(Operation, Size, Pointer) \ 00320 FreeCheck::RegisterI(Pointer, Operation, Size); 00321 #define MONITOR_REAL_DELETE(Operation, Size, Pointer) \ 00322 FreeCheck::DeRegisterR(Pointer, Operation, Size); 00323 #define MONITOR_INT_DELETE(Operation, Size, Pointer) \ 00324 FreeCheck::DeRegisterI(Pointer, Operation, Size); 00325 00326 #else // DO_FREE_CHECK not defined 00327 00328 #define FREE_CHECK(Class) public: 00329 #define MONITOR_REAL_NEW(Operation, Size, Pointer) {} 00330 #define MONITOR_INT_NEW(Operation, Size, Pointer) {} 00331 #define MONITOR_REAL_DELETE(Operation, Size, Pointer) {} 00332 #define MONITOR_INT_DELETE(Operation, Size, Pointer) {} 00333 00334 00335 #ifdef SimulateExceptions // SimulateExceptions 00336 00337 00338 #define NEW_DELETE(Class) \ 00339 public: \ 00340 void* operator new(size_t size) \ 00341 { do_not_link=true; void* t = ::operator new(size); return t; } \ 00342 void operator delete(void* t) { ::operator delete(t); } 00343 00344 #endif // end of SimulateExceptions 00345 00346 #endif // end of ! DO_FREE_CHECK 00347 00348 #ifndef SimulateExceptions // ! SimulateExceptions 00349 00350 #define NEW_DELETE(Class) FREE_CHECK(Class) 00351 00352 #endif // end of ! SimulateExceptions 00353 00354 00355 //********************* derived exceptions ******************************// 00356 00357 class Logic_error : public BaseException 00358 { 00359 public: 00360 static unsigned long Select; 00361 Logic_error(const char* a_what = 0); 00362 }; 00363 00364 class Runtime_error : public BaseException 00365 { 00366 public: 00367 static unsigned long Select; 00368 Runtime_error(const char* a_what = 0); 00369 }; 00370 00371 class Domain_error : public Logic_error 00372 { 00373 public: 00374 static unsigned long Select; 00375 Domain_error(const char* a_what = 0); 00376 }; 00377 00378 class Invalid_argument : public Logic_error 00379 { 00380 public: 00381 static unsigned long Select; 00382 Invalid_argument(const char* a_what = 0); 00383 }; 00384 00385 class Length_error : public Logic_error 00386 { 00387 public: 00388 static unsigned long Select; 00389 Length_error(const char* a_what = 0); 00390 }; 00391 00392 class Out_of_range : public Logic_error 00393 { 00394 public: 00395 static unsigned long Select; 00396 Out_of_range(const char* a_what = 0); 00397 }; 00398 00399 //class Bad_cast : public Logic_error 00400 //{ 00401 //public: 00402 // static unsigned long Select; 00403 // Bad_cast(const char* a_what = 0); 00404 //}; 00405 00406 //class Bad_typeid : public Logic_error 00407 //{ 00408 //public: 00409 // static unsigned long Select; 00410 // Bad_typeid(const char* a_what = 0); 00411 //}; 00412 00413 class Range_error : public Runtime_error 00414 { 00415 public: 00416 static unsigned long Select; 00417 Range_error(const char* a_what = 0); 00418 }; 00419 00420 class Overflow_error : public Runtime_error 00421 { 00422 public: 00423 static unsigned long Select; 00424 Overflow_error(const char* a_what = 0); 00425 }; 00426 00427 class Bad_alloc : public BaseException 00428 { 00429 public: 00430 static unsigned long Select; 00431 Bad_alloc(const char* a_what = 0); 00432 }; 00433 00434 #ifdef use_namespace 00435 } 00436 #endif 00437 00438 00439 #endif // end of EXCEPTION_LIB 00440 00441 00442 // body file: myexcept.cpp 00443 00444 00446