From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- public/sdk/inc/except.hxx | 1134 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1134 insertions(+) create mode 100644 public/sdk/inc/except.hxx (limited to 'public/sdk/inc/except.hxx') diff --git a/public/sdk/inc/except.hxx b/public/sdk/inc/except.hxx new file mode 100644 index 000000000..80afa1c46 --- /dev/null +++ b/public/sdk/inc/except.hxx @@ -0,0 +1,1134 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1991 - 1992. +// +// File: Except.hxx +// +// Contents: Macro package for C++ exception support +// +// Classes: CException -- The base for all exception classes +// CExceptionContext -- Per-thread exception context. +// CUnwindable -- Classes with destructors inherit +// from this. +// CTry -- Per/TRY state. +// +// Functions: Macros to implement TRY ... CATCH +// Macros to implement unwind for classes with destructors +// +// History: 22-May-91 KyleP Created Interface. +// 15-Aug-91 SethuR modified THROW,CATCH,AND_CATCH, +// END_CATCH macros +// 18-Oct-91 KyleP Win32 try/except implementation +// 20-Feb-92 KyleP Fixed destruction of classes with +// virtual methods. +// 03-Aug-92 KyleP Kernel implementation +// 13-Nov-92 KyleP Bugfix destruction of heap classes. +// Added assertion checking. +// 27-May-93 Mackm Added definitions for un-exceptional +// operator new. +// 01-Jun-93 RobBear Added definitions for alloc hooking +// 30-Sep-93 KyleP DEVL obsolete +// 14-Dec-93 AlexT Add NOEXCEPTIONS support +// +//---------------------------------------------------------------------------- + +#pragma warning(4:4509) // SEH used in function w/ _trycontext + +#ifndef __EXCEPT_HXX_ +#define __EXCEPT_HXX_ + +#ifdef DISPLAY_INCLUDES +#pragma message( "#include <" __FILE__ ">..." ) +#endif + +#if defined( KERNEL ) +# include +# include +#else // !KERNEL +# include +# include +# include +# include +#endif + +#include + +const int maxExceptionSize = 256; +#define DEB_BUDDY 0x10000 +#define DEB_UNWIND 0x20000 + +// +// If EXCEPT_TEST is defined, then the exception code can be compiled +// without use the the 'Win4 environment'. This is only to facilitate +// testing. When EXCEPT_TEST is defined debug messages are printed +// to stdout instead of the debug terminal. +// + +// +// REAL CODE -- REAL CODE -- REAL CODE -- REAL CODE +// + +#ifndef EXCEPT_TEST +//# if !defined( KERNEL ) +//# include +//# endif // !KERNEL +# if (DBG == 1 || OFSDBG == 1) + +// +// VERY UNUSUAL SITUATION: +// Out xxxDebugOut macros are designed to be inline. This causes +// a problem in exceptions because the _xxxInfoLevel flag which +// determines if a message should be printed is not declared in +// every DLL. So. Instead of calling the macro: +// +// DECLARE_DEBUG(ex) +// +// I will: + +void exInlineDebugOut2(unsigned long fDebugMask, char const *pszfmt, ...); + +// and then export this function from OSM.DLL (or whatever DLL +// exports exception handling. +// + +# define exDebugOut( x ) exInlineDebugOut2 x +# define exAssert( x ) Win4Assert( x ) +# else // DBG == 0 && OFSDBG == 0 +# define exDebugOut( x ) +# define exAssert( x ) +# endif + +// +// TEST ONLY -- TEST ONLY -- TEST ONLY -- TEST ONLY +// + +#else // EXCEPT_TEST + typedef unsigned long ULONG; + typedef unsigned char BYTE; +# define TRUE 1 +# include +# define exAssert( x ) assert( (x) ) + +# include +inline void exInlineDebugOut( ULONG, + char * msg, + ... ) +{ + va_list arglist; + + va_start(arglist, msg); + vfprintf(stderr, msg, arglist); +} + +# define exDebugOut( x ) exInlineDebugOut x + + +# define _PopUpError( p1, p2, p3 ) 0xFFFFFFFF +# define Win4ExceptionLevel 0xFFFFFFFF +# define EXCEPT_MESSAGE 0x1 +# define EXCEPT_POPUP 0x0 +# define EXCEPT_BREAK 0x0 +# define DEB_FORCE 0x0 +# define DEB_WARN 0x0 +# define DEB_ERROR 0x0 +# define DEB_ITRACE 0x0 + +#endif // EXCEPT_TEST + +// +// END TEST -- END TEST -- END TEST -- END TEST +// + +#if defined( WIN32 ) +# if !defined( KERNEL ) +# include +# endif // !KERNEL +#else // !WIN32 +# include +#endif // WIN32 + +class CTry; + +typedef void(*PFV)(); + +extern void terminate(); +extern void unexpected(); + +extern PFV set_terminate(PFV terminate_fn); +extern PFV set_unexpected(PFV unexpected_fn); + +#if DBG==1 || OFSDBG == 1 +typedef BOOL (* ALLOC_HOOK)(size_t nSize); +EXPORTDEF ALLOC_HOOK MemSetAllocHook( ALLOC_HOOK pfnAllocHook ); + +extern EXPORTDEF void WINAPI +ExceptionReport( + unsigned int iLine, + char *szFile, + char *szMsg); +#endif // DBG == 1 || OFSDBG == 1 + +//+--------------------------------------------------------------------------- +// +// Class: CException +// +// Purpose: All exception objects (e.g. objects that are THROW) +// inherit from CException. +// +// Interface: ~CException - Destructor +// IsKindOf - Class membership query +// +// History: 22-May-91 KyleP Created. +// +// Notes: This class is a hack, until C7 can provide some support +// for runtime inheritance detection (e.g. a way to generate +// a mangled name). When we get this support a new +// implementation of IsKindOf should be developed. The concept, +// however, would remain the same: C++ exception objects are +// instances of an exception class, but they are caught by class. +// +// A compiler can implement IsKindOf by throwing a +// decorated name which uniquely identifies a class and +// describes its inheritance. +// +// Don't do anything too fancy with subclasses of CException. +// Instances of your subclass are memcpy-ed around. Having +// a user defined destructor, for example, is probably a bad +// idea. +// +//---------------------------------------------------------------------------- + +class CException +{ +public: + + EXPORTDEF CException(long lError); + long GetErrorCode() { return _lError;} + EXPORTDEF virtual int WINAPI IsKindOf(const char * szClass) const; + +protected: + + long _lError; +}; + +//+--------------------------------------------------------------------------- +// +// Class: CExceptionContext +// +// Purpose: Per-thread exception state and throw exception methods. +// +// Interface: CExceptionContext -- Constructor +// ~CExceptionContext -- Destructor +// Push -- Push a new element on the stack of +// elements-to-be-destroyed. +// Pop -- Pop an an element off the stack. +// SetTop -- Set the top of stack to the specified +// element. +// GetTop -- Return the top element. +// Throw -- Throw an exception +// +// History: 19-Nov-91 KyleP Fix heap unwind, multiple inheritance +// 22-May-91 KyleP Created. +// +// Notes: There is only 1 CExceptionContext object per thread. +// +//---------------------------------------------------------------------------- + +class CExceptionContext +{ +public: + + CExceptionContext(); + + ~CExceptionContext(); + + EXPORTDEF void WINAPI Reserve(void * pthis); + + inline void Pop(void * pthis); + + EXPORTDEF void WINAPI SetTop(void * pthis, + ULONG cbElement, + void (* pfn)(void *)); + + inline int GetTop(); + +#ifndef WIN32 + + void Throw(); + +#endif /* WIN32 */ + + void Unwind( CTry * ptry ); + + // + // _pTopTry contains the head of a linked list of CTry objects, + // each of which corresponds to a TRY clause. + // + + CTry * _pTopTry; + + // + // _pLastNew records the address of the most recent free + // store allocation, _cbLastNew the size. + // + + BYTE * _pLastNew; + int _cbLastNew; + int _fNewReadyForUnwind; + + // + // _exception contains a pointer to the current exception, + // if any. The character buffer following it is for storing + // additional data belonging to subclasses. + // + + CException _exception; + char buffer[maxExceptionSize]; + +private: + + // + // Each StackElement contains enough information to destroy a + // completly constructed object, and the determine whether + // objects which have not yet been fully constructed were + // allocated on the heap or the stack. + // + + class StackElement + { + public: + + BOOL IsThisEqual( void * pthis ) { return( pthis == _pthis ); } + BOOL IsSizeEqual( ULONG cb ) { return( cb == _cbElement ); } + BOOL IsOnStack() { return( _cbElement == 0 ); } + BOOL IsOnHeap() { return( _cbElement != 0 ); } + BOOL IsActive() { return( _pfn != 0 ); } + + void SetOnStack() { _cbElement = 0; } + void SetOnHeap( ULONG size ) { _cbElement = size; } + void SetThis( void * pthis ) { _pthis = pthis; } + void SetDtor( void (* pfn)(void *) ) { _pfn = pfn; } + + void * GetDtor() { return( _pfn ); } + void * GetThis() { return( _pthis ); } + + void Destroy() { _pfn( (BYTE *)_pthis ); } + void Delete() { delete (BYTE *)_pthis; } + + private: + + void * _pthis; // This for CUnwindable + void (* _pfn)(void *); // 'Static destructor' + ULONG _cbElement; // 0 == On stack. > 0 = Size of class + }; + + // + // _aStack is the stack of objects-to-be-destroyed in the face + // of an exception (stack unwind). + // + + StackElement * _aStack; + + // + // _StackTop is the index of the first free element on the stack. + // + + int _StackTop; + + // + // _StackSize is the maximum number of elements which can be + // stored on the stack. + // + + int _StackSize; + + + EXPORTDEF void APINOT _Grow(); + +}; + +//+--------------------------------------------------------------------------- +// +// Member: CExceptionContext::Pop, public +// +// Synopsis: Pops the top element off the stack of objects to be destroyed. +// +// Effects: Pop only has an effect if the top element on the stack +// is for [pthis]. +// +// Arguments: [pthis] -- Must correspond to the top of stack if the +// element is to be popped. +// +// History: 22-May-91 KyleP Created. +// +//---------------------------------------------------------------------------- + +inline void CExceptionContext::Pop(void * pthis) +{ + // + // Remove the top of stack only if it corresponds to pthis. + // Thus the element will be removed only if this object was + // declared on the stack (as opposed to embedded) and no + // exception was encountered. + // + + // + // You should *always* find what you're looking for. No checking + // for runoff. The very bottom element of the stack is a sentinel + // for the case of heap objects which have been fully removed from + // the stack. + // + + exAssert( _StackTop > 0 ); + + if ( _aStack[_StackTop-1].IsThisEqual( pthis ) ) + { + // + // The following assertion is hit if an unwindable object + // is destroyed without END_CONSTRUCTION being called. + // + + exAssert( _aStack[_StackTop-1].IsActive() ); + + _StackTop--; + +#if DBG == 1 || OFSDBG == 1 + exDebugOut(( DEB_ITRACE, "POP %lx %lx( %lx )\n", + _StackTop, + _aStack[_StackTop].GetDtor(), + _aStack[_StackTop].GetThis() )); +#endif // DBG || OFSDBG == 1 + } +} + +//+--------------------------------------------------------------------------- +// +// Member: CExceptionContext::GetTop, public +// +// Returns: The index of the top of the stack of objects to be +// destroyed. This is the first available element. +// +// History: 22-May-91 KyleP Created. +// +//---------------------------------------------------------------------------- + +inline int CExceptionContext::GetTop() +{ + return(_StackTop); +} + +EXPORTDEF CExceptionContext& APINOT _ExceptionContext(void); + +//---------------------------------------------------------------------------- +// +// Various operator new implementations +// +//---------------------------------------------------------------------------- + +EXPORTDEF int APINOT LeakCheck ( ULONG* pCount ); + +#if defined( KERNEL ) + +// +// Prototype for extra operator new used in kernel to specify +// resident vs. swappable heap. +// + +void InitExceptionSystem(); +void* _CRTAPI1 operator new ( size_t size, POOL_TYPE pool ); + +#if OFSDBG == 1 +# define NEW_POOL( pool, pCounter ) new(pool, pCounter) + void* _CRTAPI1 operator new ( size_t size, POOL_TYPE pool, ULONG* pCounter ); +#else +# define NEW_POOL( pool, pCounter ) new(pool) +#endif + +#endif // KERNEL + +// +// Allocation with trace context +// + +#if OFSDBG == 1 || DBG == 1 +# define NEW( pCounter ) new ( pCounter ) + void* _CRTAPI1 operator new ( size_t size, ULONG* pCounter ); +#else +# define NEW( pCounter ) new +#endif + +// +// Prototype for extra operator new used in routines which do not +// have an exception handler set up and prefer a null return on +// failed allocations rather than an exception. +// + +typedef enum _FAIL_BEHAVIOR +{ + NullOnFail, // BUGBUG: should be deleted ASAP + ExceptOnFail +} FAIL_BEHAVIOR ; + +void* _CRTAPI1 operator new ( size_t size, FAIL_BEHAVIOR FailBehavior ); + +#define newx new(ExceptOnFail) + +//+--------------------------------------------------------------------------- +// +// Class: CSystemException +// +// Purpose: Base class for system (hardware) exceptions which are +// not handled by a specific exception class +// +// Interface: +// +// History: 18-Oct-91 KyleP Created. +// +//---------------------------------------------------------------------------- + +class CSystemException : public CException +{ +public: + + EXPORTDEF CSystemException(ULONG ulExcept); + + virtual int WINAPI IsKindOf(const char * szClass) const; + + ULONG GetSysErrorCode() { return( _ulExcept ); } + +private: + + ULONG _ulExcept; + +}; + +//+--------------------------------------------------------------------------- +// +// Class: CUnwindable, CVirtualUnwindable +// +// Purpose: Per-object exception state and registration/unwind methods. +// +// Interface: CUnwindable -- Constructor +// ~CUnwindable -- Destructor +// _Activate -- Activate object. +// +// History: 22-May-91 KyleP Created. +// 13-Nov-92 KyleP Added virtual version +// +// Notes: CVirtualUnwindable should be used if and only if a +// derived class has some other virtual method. +// +//---------------------------------------------------------------------------- + +class CUnwindable +{ +public: + + inline CUnwindable(); + + inline ~CUnwindable(); + + inline void _Activate( ULONG cbElement, + void (* pfn)(void *) ); +}; + +class CVirtualUnwindable +{ +public: + + inline CVirtualUnwindable(); + + virtual ~CVirtualUnwindable(); + + inline void _Activate( ULONG cbElement, + void (* pfn)(void *) ); +}; + +//+--------------------------------------------------------------------------- +// +// Member: CUnwindable::CUnwindable, public +// +// Synopsis: Initializes the link field of the object. +// +// Effects: Essentially sets up enough state to remember the position +// of the object which inherits from CUnwindable +// within the stack of objects-to-be-destroyed. +// +// History: 22-May-91 KyleP Created. +// +// Notes: This call does not fully link the object into the chain +// of objects to be destroyed. See _Activate. +// +//---------------------------------------------------------------------------- + +inline CUnwindable::CUnwindable() +{ + // + // Initialize by allocating a record on the deletion stack. + // + + _ExceptionContext().Reserve(this); +} + +inline CVirtualUnwindable::CVirtualUnwindable() +{ + // + // Initialize by allocating a record on the deletion stack. + // + + _ExceptionContext().Reserve(this); +} + +//+--------------------------------------------------------------------------- +// +// Member: CUnwindable::~CUnwindable, public +// +// Synopsis: Removes this object from the stack of objects to be destroyed. +// +// Modifies: Per/thread exception context. +// +// History: 22-May-91 KyleP Created. +// +//---------------------------------------------------------------------------- + +inline CUnwindable::~CUnwindable() +{ + _ExceptionContext().Pop(this); +} + +inline CVirtualUnwindable::~CVirtualUnwindable() +{ + _ExceptionContext().Pop(this); +} + +//+--------------------------------------------------------------------------- +// +// Member: CUnwindable::_Activate, public +// +// Synopsis: Fully link object into stack of objects to be destroyed. +// +// Effects: After this call, the object which inherits from +// CUnwindable will be destroyed during unwind. +// +// If the object was declared on the heap, then it is +// removed completely from the stack of objects that will +// be destroyed during unwind. +// +// Arguments: [prealthis] -- This pointer of instance. Will differ +// from this pointer of CUnwindable +// if instance has a virtual method. +// [cbElement] -- Size of the instance being activated. If +// an element is declared on the heap and +// [cbElement] is smaller than the allocation +// then the element won't be deleted. +// +// [pfn] -- Pointer to a static destructor. [pfn] takes a +// this pointer. +// +// Modifies: This object is now the top of the stack of objects that +// will be destroyed (_exceptioncontext is modified). +// +// History: 22-May-91 KyleP Created. +// +//---------------------------------------------------------------------------- + +inline void CUnwindable::_Activate( + ULONG cbElement, + void (* pfn)(void *)) +{ + _ExceptionContext().SetTop(this, cbElement, pfn); +} + +inline void CVirtualUnwindable::_Activate( + ULONG cbElement, + void (* pfn)(void *)) +{ + _ExceptionContext().SetTop(this, cbElement, pfn); +} + +//+--------------------------------------------------------------------------- +// +// Class: CTry +// +// Purpose: Containt per/TRY state. +// +// Interface: ~CTry - Destructor +// TryIt - Setup to run the TRY body. +// +// History: 22-May-91 KyleP Created. +// +//---------------------------------------------------------------------------- + +class CTry +{ +public: + + inline CTry(); + inline ~CTry(); + + // + // The following function ***MUST*** be declared inline and + // actually be ***IMPLEMENTED*** inline. It calls setjmp; + // and if TryIt is a real procedure then we just set the + // return for longjmp on a piece of stack that is reclaimed! + // + + //inline int TryIt(); + +#ifndef WIN32 + + // + // _jb is the setjmp buffer indicating the location that will + // be longjmp'ed to when an exception occurs. + // + + jmp_buf _jb; + +#endif /* WIN32 */ + + // + // _pPrevTry is a link to the enclosing TRY clause. + // + + CTry * _pPrevTry; + + // + // _StackTop was the top of the stack of objects-to-be-destroyed + // when the TRY clause was entered. + // + + int _StackTop; +}; + +//+--------------------------------------------------------------------------- +// +// Member: CTry::~CTry, public +// +// Synopsis: Unlinks the TRY ... CATCH from the per/thread list. +// +// Modifies: The per/thread list of try clauses in _exceptioncontext. +// +// History: 22-May-91 KyleP Created. +// +//---------------------------------------------------------------------------- + +inline CTry::~CTry() +{ + exDebugOut(( DEB_ITRACE, "END TRY %lx (%lx)\n", _StackTop, this )); + + // + // The destructor for CTry is called only during normal (no + // exception) exit from the TRY ... CATCH or when an + // exception was successfully caught in this block. + // In these cases we want to unlink this CTry. + // + // Note that we could delete _exceptioncontext._TheException + // here, which may be non-null if we caught an exception in + // this TRY ... CATCH block. But why bother? That would add + // additional code to the normal case. The last exception + // can wait to be deleted until the next occurs. + // + + _ExceptionContext()._pTopTry = _pPrevTry; +} + +//+--------------------------------------------------------------------------- +// +// Member: CTry::CTry, public +// +// Synopsis: Set up to run the body of a TRY ... CATCH clause. +// +// Effects: Links this CTry into the chain of TRY clauses. +// +// History: 22-May-91 KyleP Created. +// +//---------------------------------------------------------------------------- + +inline CTry::CTry() +{ + CExceptionContext& _exceptioncontext = _ExceptionContext(); + + _pPrevTry = _exceptioncontext._pTopTry; + _exceptioncontext._pTopTry = this; + _StackTop = _exceptioncontext.GetTop(); + + exDebugOut(( DEB_ITRACE, "TRY %lx (%lx)\n", _StackTop, this )); +} + +//+--------------------------------------------------------------------------- +// +// The following macros implement a TRY ... CATCH syntax similar +// to that in C++. They are used as follows: +// +// TRY +// { +// // Body of try goes here... +// } +// CATCH(exclass, e) +// { +// // We get here when an exception of class exclass has +// // been thrown. The variable e is declared as * exclass. +// } +// AND_CATCH(exclass, e) +// { +// // Just like CATCH. Any number of AND_CATCH can follow +// // CATCH. Handlers are tried in order of appearance. +// } +// END_CATCH +// +// To throw an exception, use the THROW macro -- THROW(exclass). To +// re-throw the same exception from within a catch clause use +// RETHROW(). Note that RETHROW() is only valid in a CATCH/AND_CATCH. +// +// History: 22-May-91 KyleP Created Interface. +// 15-Aug-91 SethuR modified THROW,CATCH,AND_CATCH,END_CATCH +// macros +// 18-Oct-91 KyleP Win32 try/except implementation +// +//---------------------------------------------------------------------------- + +extern EXPORTDEF void APINOT ThrowDebugException(unsigned int iLine, + char * szFile, + CException & ecE ); + +extern EXPORTDEF void APINOT ThrowException(CException & ecE, + unsigned dummy); + +#if DBG == 1 || OFSDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++ +# define THROW(e) \ + { \ + ThrowDebugException(__LINE__,__FILE__,e); \ + } + +#else // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++ + +# define THROW(e) \ + { \ + ThrowException(e, 1); \ + } + +#endif // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++ + + +#ifdef WIN32 // ---------------------------------------------------- + +#define EXCEPT_VULCAN 0xE0000001 + +# define CALLEX( x ) \ + __try \ + { \ + x; \ + } \ + __except( EXCEPTION_EXECUTE_HANDLER ) \ + { \ + THROW( CException( GetExceptionCode() ) ); \ + } + +#if defined( KERNEL ) +# if DBG == 1 || OFSDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++ +# define RETHROW() \ + ExceptionReport(__LINE__,__FILE__,"Rethrowing Exception"); \ + ExRaiseStatus( EXCEPT_VULCAN ); + +# else // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++ + +# define RETHROW() \ + ExRaiseStatus( EXCEPT_VULCAN ); + +# endif // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++ + + +#else // !KERNEL +# if DBG == 1 || OFSDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++ +# define RETHROW() \ + ExceptionReport(__LINE__,__FILE__,"Rethrowing Exception"); \ + RaiseException( EXCEPT_VULCAN, 0, 0, 0 ); +# else // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++ + +# define RETHROW() \ + RaiseException( EXCEPT_VULCAN, 0, 0, 0 ); + +# endif // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++ + +#endif // !KERNEL + +#define TRY \ + { \ + CTry _trycontext; \ + __try + +EXPORTDEF ULONG APINOT Unwind( struct _EXCEPTION_POINTERS * pdisp, + CTry * ptry ); + +#if DBG == 1 || OFSDBG == 1 // +++++++++++++++++++++++++++++++++++++++++++++++ + +#define CATCH(class, e) \ + __except( Unwind( GetExceptionInformation(), &_trycontext ) ) \ + { \ + CExceptionContext& _exceptioncontext = _ExceptionContext(); \ + if (_exceptioncontext._exception.IsKindOf(#class)) \ + { \ + ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \ + class & e = (class &)_exceptioncontext._exception; + +#define AND_CATCH(class, e) \ + } \ + else if (_exceptioncontext._exception.IsKindOf(#class)) \ + { \ + ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \ + class & e = (class &)_exceptioncontext._exception; + +#else // DBG == 0 ++++++++++++++++++++++++++++++++++++++++++++ + +#define CATCH(class, e) \ + __except( Unwind( GetExceptionInformation(), &_trycontext ) ) \ + { \ + CExceptionContext& _exceptioncontext = _ExceptionContext(); \ + if (_exceptioncontext._exception.IsKindOf(#class)) \ + { \ + class & e = (class &)_exceptioncontext._exception; + +#define AND_CATCH(class, e) \ + } \ + else if (_exceptioncontext._exception.IsKindOf(#class)) \ + { \ + class & e = ( class &)_exceptioncontext._exception; + +#endif // DBG == 0 +++++++++++++++++++++++++++++++++++++++++++ + +#define END_CATCH \ + } \ + else \ + { \ + RETHROW(); \ + } \ + } \ + } + +#else // NOT WIN32 ------------------------------------------------- + +#define TRY \ + { \ + CTry _trycontext; \ + if (setjmp(_trycontext._jb) == 0) \ + + + +#if DBG == 1 || OFSDBG == 1 // ++++++++++++++++++++++++++++++++++++++++++++++++ + +#define CATCH(class, e) \ + \ + else \ + { \ + CExceptionContext& _exceptioncontext = _ExceptionContext(); \ + if (_exceptioncontext._exception.IsKindOf(#class)) \ + { \ + ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \ + class & e = (class &)_exceptioncontext._exception; + +#define AND_CATCH(class, e) \ + \ + } \ + else if (_exceptioncontext._exception.IsKindOf(#class)) \ + { \ + ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \ + class & e = (class &)_exceptioncontext._exception; + + +#else // DBG == 0 +++++++++++++++++++++++++++++++++++++++++++++ + +#define CATCH(class, e) \ + \ + else \ + { \ + CExceptionContext& _exceptioncontext = _ExceptionContext(); \ + if (_exceptioncontext._exception.IsKindOf(#class)) \ + { \ + class & e = (class &)_exceptioncontext._exception; + +#define AND_CATCH(class, e) \ + \ + } \ + else if (_exceptioncontext._exception.IsKindOf(#class)) \ + { \ + class & e = (class &)_exceptioncontext._exception; + +#endif // DBG == 0 +++++++++++++++++++++++++++++++++++++++++++ + + +#define END_CATCH \ + } \ + else \ + { \ + _exceptioncontext.Throw(); \ + } \ + } \ + } + +#define RETHROW() \ + _exceptioncontext.Throw() + +#endif // NOT WIN32 ------------------------------------------------ + +//+--------------------------------------------------------------------------- +// +// The following macros prepare a class for stack unwinding. Any class +// with a destructor should be prepared to deal with stack unwind. +// The macros are used as follows: +// +// First, in the .hxx file... +// +// class CClassWithADestructor : INHERIT_UNWIND // , other inheritance +// { +// DECLARE_UNWIND +// +// // +// // The rest of the class declaration goes here... +// // +// } +// +// And then in the .cxx file... +// +// IMPLEMENT_UNWIND(CClassWithADestructor) +// +// CClassWithADestructor::CClassWithADestructor(...) +// { +// // +// // User construction activity. +// // +// +// // +// // The following should precede every return from the +// // constructor. +// // +// +// END_CONSTRUCTION(CClassWithADestructor) +// } +// +// INHERIT_UNWIND must be the first inheritance. +// +// For further levels of inheritance, you do not need to inherit from +// INHERIT_UNWIND (more to the point, you can't). The other macros +// must be used for all levels. +// +// INHERIT_VIRTUAL_UNWIND must be used in place of INHERIT_UNWIND on a class +// that contains virtual methods. If INHERIT_VIRTUAL_UNWIND also fails, +// then find me (KyleP) and I'll try to figure out what went wrong. +// +// Multiple inheritance is untested. It may work, or it may not. If you +// really need multiple inheritance see me (KyleP). +// +// History: 19-Nov-91 KyleP Added multiple-inheritance support +// 22-May-91 KyleP Created Interface. +// 13-Nov-92 KyleP Added support for classes with virtual +// methods. +// +//---------------------------------------------------------------------------- + +#define INHERIT_UNWIND \ + \ + public CUnwindable + +#define INHERIT_VIRTUAL_UNWIND \ + \ + public CVirtualUnwindable + + +#define END_MULTINHERITED_CONSTRUCTION(class, base1) \ + \ + base1::_Activate(sizeof(class), &class::_ObjectUnwind); + + +// +// Why such a complicated test below? Because we are nearly ready to +// ship Daytona and Ole includes except.hxx but requires the macros +// do nothing. We are unable to change the Ole sources this late in +// the game, so you get exceptions only if you are: +// a) In a Cairo build and didn't define NOEXCEPTIONS, or +// b) Defined YESEXCEPTIONS in any build. +// +// The above would be true and interesting if anybody except OFS wanted +// to use ofsNew or ofsDelete. As it is, the declarations below (and +// most of the rest of this file) should be moved to the OFS project +// +#if ((WIN32 == 300) && !defined(NOEXCEPTIONS)) || defined(YESEXCEPTIONS) + +#if (OFSDBG == 1) + void* _CRTAPI1 ofsNew( size_t size, FAIL_BEHAVIOR FailBehavior ); + inline void* _CRTAPI1 operator new ( size_t size, FAIL_BEHAVIOR FailBehavior) + { return ofsNew(size, FailBehavior); } + + void _CRTAPI1 ofsDelete( void * p ); + inline void _CRTAPI1 operator delete ( void * p ) + { ofsDelete( p ); } +#endif // (OFSDBG == 1) + +#define INHERIT_UNWIND_IF_CAIRO : INHERIT_UNWIND + +#define DECLARE_UNWIND \ + \ + static void APINOT _ObjectUnwind(void * pthis); + +#if DBG == 1 || OFSDBG == 1 + +# define IMPLEMENT_UNWIND(class) \ + \ + void APINOT class::_ObjectUnwind(void * pthis) \ + { \ + ((class *)pthis)->class::~class(); \ + } \ + \ + struct __Check##class \ + { \ + __Check##class() \ + { \ + if ( (CUnwindable *)((class *)10) != (CUnwindable *)10 || \ + (CVirtualUnwindable *) \ + ((class *)10) != (CVirtualUnwindable *)10 ) \ + { \ + exDebugOut(( DEB_ERROR, \ + "INVALID UNWINDABLE CLASS: %s.\n", \ + #class )); \ + } \ + } \ + }; \ + \ + __Check##class __check_except_##class; + +#else // DBG == 0 + +# define IMPLEMENT_UNWIND(class) \ + \ + void APINOT class::_ObjectUnwind(void * pthis) \ + { \ + ((class *)pthis)->class::~class(); \ + } + +#endif // DBG + +#define END_CONSTRUCTION(class) \ + \ + _Activate( sizeof(class), &class::_ObjectUnwind ); + +// The following macro will (probably) need to be redefined (to null) when +// compiler support for exceptions arrives. + +#define INLINE_UNWIND(cls) \ + static void _ObjectUnwind ( void * pthis ) \ + { ((cls *)pthis)->cls::~cls(); }; +#else + +#define INHERIT_UNWIND_IF_CAIRO + +#define DECLARE_UNWIND + +#define END_CONSTRUCTION(class) + +#define INLINE_UNWIND(cls) + +#define IMPLEMENT_UNWIND(cls) + +#endif + +#endif // __EXCEPT_HXX__ -- cgit v1.2.3