You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

447 lines
12 KiB
C++

/// \ingroup rbd_common
///@{
/// \file myexcept.h
/// Exception handler.
/// The low level classes for
/// - my exception class hierarchy
/// - the functions needed for my simulated exceptions
/// - the Tracer mechanism
/// - routines for checking whether new and delete calls are balanced
///
// A set of classes to simulate exceptions in C++
//
// Partially copied from Carlos Vidal s article in the C users journal
// September 1992, pp 19-28
//
// Operations defined
// Try { }
// Throw ( exception object )
// ReThrow
// Catch ( exception class ) { }
// CatchAll { }
// CatchAndThrow
//
// All catch lists must end with a CatchAll or CatchAndThrow statement
// but not both.
//
// When exceptions are finally implemented replace Try, Throw(E), Rethrow,
// Catch, CatchAll, CatchAndThrow by try, throw E, throw, catch,
// catch(...), and {}.
//
// All exception classes must be derived from BaseException, have no
// non-static variables and must include the statement
//
// static unsigned long Select;
//
// Any constructor in one of these exception classes must include
//
// Select = BaseException::Select;
//
// For each exceptions class, EX_1, some .cpp file must include
//
// unsigned long EX_1::Select;
//
#ifndef EXCEPTION_LIB
#define EXCEPTION_LIB
#include "include.h"
#ifdef use_namespace
namespace RBD_COMMON {
#endif
void Terminate();
//********** classes for setting up exceptions and reporting ************//
class BaseException;
class Tracer // linked list showing how
{ // we got here
const char* entry;
Tracer* previous;
public:
Tracer(const char*);
~Tracer();
void ReName(const char*);
static void PrintTrace(); // for printing trace
static void AddTrace(); // insert trace in exception record
static Tracer* last; // points to Tracer list
friend class BaseException;
};
class BaseException // The base exception class
{
protected:
static char* what_error; // error message
static int SoFar; // no. characters already entered
static int LastOne; // last location in error buffer
public:
static void AddMessage(const char* a_what);
// messages about exception
static void AddInt(int value); // integer to error message
static unsigned long Select; // for identifying exception
BaseException(const char* a_what = 0);
static const char* what() { return what_error; }
// for getting error message
};
#ifdef TypeDefException
typedef BaseException Exception; // for compatibility with my older libraries
#endif
inline Tracer::Tracer(const char* e)
: entry(e), previous(last) { last = this; }
inline Tracer::~Tracer() { last = previous; }
inline void Tracer::ReName(const char* e) { entry=e; }
#ifdef SimulateExceptions // SimulateExceptions
#include <setjmp.h>
//************* the definitions of Try, Throw and Catch *****************//
class JumpItem;
class Janitor;
class JumpBase // pointer to a linked list of jmp_buf s
{
public:
static JumpItem *jl;
static jmp_buf env;
};
class JumpItem // an item in a linked list of jmp_buf s
{
public:
JumpItem *ji;
jmp_buf env;
Tracer* trace; // to keep check on Tracer items
Janitor* janitor; // list of items for cleanup
JumpItem() : ji(JumpBase::jl), trace(0), janitor(0)
{ JumpBase::jl = this; }
~JumpItem() { JumpBase::jl = ji; }
};
void Throw();
inline void Throw(const BaseException&) { Throw(); }
#define Try \
if (!setjmp( JumpBase::jl->env )) { \
JumpBase::jl->trace = Tracer::last; \
JumpItem JI387256156;
#define ReThrow Throw()
#define Catch(EXCEPTION) \
} else if (BaseException::Select == EXCEPTION::Select) {
#define CatchAll } else
#define CatchAndThrow } else Throw();
//****************** cleanup heap following Throw ***********************//
class Janitor
{
protected:
static bool do_not_link; // set when new is called
bool OnStack; // false if created by new
public:
Janitor* NextJanitor;
virtual void CleanUp() {}
Janitor();
virtual ~Janitor();
};
// The tiresome old trick for initializing the Janitor class
// this is needed for classes derived from Janitor which have objects
// declared globally
class JanitorInitializer
{
public:
JanitorInitializer();
private:
static int ref_count;
};
static JanitorInitializer JanInit;
#endif // end of SimulateExceptions
#ifdef UseExceptions
#define Try try
#define Throw(E) throw E
#define ReThrow throw
#define Catch catch
#define CatchAll catch(...)
#define CatchAndThrow {}
#endif // end of UseExceptions
#ifdef DisableExceptions // Disable exceptions
#define Try {
#define ReThrow Throw()
#define Catch(EXCEPTION) } if (false) {
#define CatchAll } if (false)
#define CatchAndThrow }
inline void Throw() { Terminate(); }
inline void Throw(const BaseException&) { Terminate(); }
#endif // end of DisableExceptions
#ifndef SimulateExceptions // ! SimulateExceptions
class Janitor // a dummy version
{
public:
virtual void CleanUp() {}
Janitor() {}
virtual ~Janitor() {}
};
#endif // end of ! SimulateExceptions
//******************** FREE_CHECK and NEW_DELETE ***********************//
#ifdef DO_FREE_CHECK // DO_FREE_CHECK
// Routines for tracing whether new and delete calls are balanced
class FreeCheck;
class FreeCheckLink
{
protected:
FreeCheckLink* next;
void* ClassStore;
FreeCheckLink();
virtual void Report()=0; // print details of link
friend class FreeCheck;
};
class FCLClass : public FreeCheckLink // for registering objects
{
char* ClassName;
FCLClass(void* t, char* name);
void Report();
friend class FreeCheck;
};
class FCLRealArray : public FreeCheckLink // for registering real arrays
{
char* Operation;
int size;
FCLRealArray(void* t, char* o, int s);
void Report();
friend class FreeCheck;
};
class FCLIntArray : public FreeCheckLink // for registering int arrays
{
char* Operation;
int size;
FCLIntArray(void* t, char* o, int s);
void Report();
friend class FreeCheck;
};
class FreeCheck
{
static FreeCheckLink* next;
static int BadDelete;
public:
static void Register(void*, char*);
static void DeRegister(void*, char*);
static void RegisterR(void*, char*, int);
static void DeRegisterR(void*, char*, int);
static void RegisterI(void*, char*, int);
static void DeRegisterI(void*, char*, int);
static void Status();
friend class FreeCheckLink;
friend class FCLClass;
friend class FCLRealArray;
friend class FCLIntArray;
};
#define FREE_CHECK(Class) \
public: \
void* operator new(size_t size) \
{ \
void* t = ::operator new(size); FreeCheck::Register(t,#Class); \
return t; \
} \
void operator delete(void* t) \
{ FreeCheck::DeRegister(t,#Class); ::operator delete(t); }
#ifdef SimulateExceptions // SimulateExceptions
#define NEW_DELETE(Class) \
public: \
void* operator new(size_t size) \
{ \
do_not_link=true; \
void* t = ::operator new(size); FreeCheck::Register(t,#Class); \
return t; \
} \
void operator delete(void* t) \
{ FreeCheck::DeRegister(t,#Class); ::operator delete(t); }
#endif // end of SimulateExceptions
#define MONITOR_REAL_NEW(Operation, Size, Pointer) \
FreeCheck::RegisterR(Pointer, Operation, Size);
#define MONITOR_INT_NEW(Operation, Size, Pointer) \
FreeCheck::RegisterI(Pointer, Operation, Size);
#define MONITOR_REAL_DELETE(Operation, Size, Pointer) \
FreeCheck::DeRegisterR(Pointer, Operation, Size);
#define MONITOR_INT_DELETE(Operation, Size, Pointer) \
FreeCheck::DeRegisterI(Pointer, Operation, Size);
#else // DO_FREE_CHECK not defined
#define FREE_CHECK(Class) public:
#define MONITOR_REAL_NEW(Operation, Size, Pointer) {}
#define MONITOR_INT_NEW(Operation, Size, Pointer) {}
#define MONITOR_REAL_DELETE(Operation, Size, Pointer) {}
#define MONITOR_INT_DELETE(Operation, Size, Pointer) {}
#ifdef SimulateExceptions // SimulateExceptions
#define NEW_DELETE(Class) \
public: \
void* operator new(size_t size) \
{ do_not_link=true; void* t = ::operator new(size); return t; } \
void operator delete(void* t) { ::operator delete(t); }
#endif // end of SimulateExceptions
#endif // end of ! DO_FREE_CHECK
#ifndef SimulateExceptions // ! SimulateExceptions
#define NEW_DELETE(Class) FREE_CHECK(Class)
#endif // end of ! SimulateExceptions
//********************* derived exceptions ******************************//
class Logic_error : public BaseException
{
public:
static unsigned long Select;
Logic_error(const char* a_what = 0);
};
class Runtime_error : public BaseException
{
public:
static unsigned long Select;
Runtime_error(const char* a_what = 0);
};
class Domain_error : public Logic_error
{
public:
static unsigned long Select;
Domain_error(const char* a_what = 0);
};
class Invalid_argument : public Logic_error
{
public:
static unsigned long Select;
Invalid_argument(const char* a_what = 0);
};
class Length_error : public Logic_error
{
public:
static unsigned long Select;
Length_error(const char* a_what = 0);
};
class Out_of_range : public Logic_error
{
public:
static unsigned long Select;
Out_of_range(const char* a_what = 0);
};
//class Bad_cast : public Logic_error
//{
//public:
// static unsigned long Select;
// Bad_cast(const char* a_what = 0);
//};
//class Bad_typeid : public Logic_error
//{
//public:
// static unsigned long Select;
// Bad_typeid(const char* a_what = 0);
//};
class Range_error : public Runtime_error
{
public:
static unsigned long Select;
Range_error(const char* a_what = 0);
};
class Overflow_error : public Runtime_error
{
public:
static unsigned long Select;
Overflow_error(const char* a_what = 0);
};
class Bad_alloc : public BaseException
{
public:
static unsigned long Select;
Bad_alloc(const char* a_what = 0);
};
#ifdef use_namespace
}
#endif
#endif // end of EXCEPTION_LIB
// body file: myexcept.cpp
///@}