home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 31
/
CDASC_31_1996_juillet_aout.iso
/
vrac
/
cuj0796.zip
/
LETTERS.ZIP
/
REDEFAFX.H
< prev
Wrap
Text File
|
1996-04-30
|
8KB
|
218 lines
// redefafx.h
// bug fixed by Vesely on 30 apr 96
//
// Arranged by Vesely in Milan from MFC 3.0 afx.h, which is an instance
// of the Microsoft Foundation Classes C++ library, which is
// Copyright (C) 1992 Microsoft Corporation
//
// This header file is included after <afx.h> in the "stdafx.h" header,
// also in the one which is precompiled to build the MFC 2.52 class library.
// The purpose of rebuilding the library is to take advantage of the
// Exception Handling feature in a 16 bits compiler: the exception
// handling macros are redefined in order to do real C++ exceptions,
// instead of setjmp/longjmp.
//
// Note for upward compatibility
// =============================
// the macro redefinitions presented hereafter are similar to the
// definitions used in MFC30. As defined below, one does step by
// step unwinding, i.e. each try block on the call stack is visited.
// In this respect, MFC30 is closer to the standard. MFC30 internally
// redefines the macros to be even closer to the standard, and avoid
// building AFX_EXCEPTION_LINK every time a TRY is entered. Handlers need
// to use the DELETE_EXCEPTION/NO_CPP_EXCEPTION mutually exclusive macros.
//
// AFX_EXCEPTION_LINK usage can be avoided in MFC25 too, provided that
// handlers code is upgraded to use DELETE_EXCEPTION for all CException-
// derived exceptions that are build on the heap. (Notice that, obviously,
// CMemoryException objects are NOT build on the heap.)
// In that case, upgrade macros redefinitions accordingly,
// i.e. not building and not asserting the AFX_EXCEPTION_LINKs.
//
// For using regular try/catch/throw statements instead of macros,
// and still be compatible with code that uses the macros,
// one must delete CExceptions in the handlers and arrange for OnThrow
// to be called from the compiler-specific throw functions, the latter
// being very unportable. A good compromise seems use try/catch,
// but use macros or special functions for THROW, until the exception
// monitor or equivalent functionality will possibly be standardized.
/////////////////////////////////////////////////////////////////////////////
// Exception macros using try, catch and CppThrow
// (source compatibile to versions 2.5x of MFC)
#if defined( CPP_EXCEPTIONS)
#if 1 // workaround for Symantec v 7.0r1 bug:
// ~AFX_EXCEPTION_LINK is not called during stack unwinding
// because it is a __near struct in a large memory model
// remove the patch when the bug will be fixed
class WorkaroundBug : public AFX_EXCEPTION_LINK
{
public:
~WorkaroundBug() {}
};
#define AFX_EXCEPTION_LINK_ WorkaroundBug
#else
#define AFX_EXCEPTION_LINK_ AFX_EXCEPTION_LINK
#endif // workaround for Symantec v 7.0r1 bug
// replacement for AfxThrow
void AFXAPI CppThrow(CException* pException, BOOL bShared);
// after some thought, I've decided to keep the exception
// monitor in the retail build, to enable destructors to test
// if stack unwinding is currently being performed, before
// possibly throwing an exception
class CExceptionMonitor
{
public:
typedef void(*Callback)( BOOL bStartUnwinding);
private:
static int m_nCount;
static Callback m_pfCallback;
BOOL m_bResumed;
friend void AFXAPI CppThrow(CException* pException,
BOOL bShared); // calls here
static void OnThrow(); // just before each throw
public:
CExceptionMonitor() : m_bResumed( FALSE)
{
// there must be one auto object inside each handler's block,
// as done in the macro redefinitions below
ASSERT( m_nCount > 0);
}
~CExceptionMonitor();
// manually called from a handler to mean the exception
// has been handled. Technically, the exception is
// handled as soon as the handler gets control.
// However, most handlers just do manual cleanup,
// so it seems meaningful to extend the critical zone.
void Resume();
// can be tested in object destructors before throwing
static BOOL Unwinding() { ASSERT( m_nCount >= 0); return m_nCount; }
// can be used to set a callback
static Callback HookOnThrow( Callback newCallback);
};
#if defined( _DEBUG)
class CDebugException : public CException
// only CATCH_ALL/END_CATCH_ALL get this:
// CATCH( CDebugException, e) => compile error in retail build
{
DECLARE_DYNAMIC( CDebugException)
public:
CDebugException();
};
// this intermittently throws the relevant exception
void ThrowPointTest( CRuntimeClass *pE, LPCSTR lpszFileName, int nLine);
#define EXCEPTIONS_CAN_BE_THROWN(e) \
ThrowPointTest( RUNTIME_CLASS( e), THIS_FILE, __LINE__)
#else
#define EXCEPTIONS_CAN_BE_THROWN(e) ((void)0)
#endif // _DEBUG
#undef TRY
#define TRY { AFX_EXCEPTION_LINK_ _afxExceptionLink; \
try { EXCEPTIONS_CAN_BE_THROWN( CDebugException); {
/////////////////////////////////////////////////////
// BUG FIX: all the catch clauses are gathered under
// a unique catch block, and the type of exception is
// resolved on the catch side.
// As dynamic_cast is not quite as robust as MFC's
// IsKindOf, I use the latter.
// Note: this new arrangement makes it an error to do
// AND_CATCH_ALL(E) /* something */ END_CATCH: must
// use END_CATCH_ALL, as it was in MFC 2.x.
#undef CATCH
// CATCH can only be the first handler in the list:
// in the (rare) case of a handler list with more than one
// meaningful selective handler, EXCEPTIONS_CAN_BE_THROWN
// needs to be coded explicitely.
#define CATCH(class, e) EXCEPTIONS_CAN_BE_THROWN( class); } \
} catch (CException*) { \
CExceptionMonitor ExceptionMonitor; \
if ( _afxExceptionLink.m_pException-> \
IsKindOf( RUNTIME_CLASS( class))) \
{ class *e = (class*) _afxExceptionLink.m_pException;
#undef AND_CATCH
#define AND_CATCH(class, e) } else if \
( _afxExceptionLink.m_pException->IsKindOf( RUNTIME_CLASS( class))) \
{ class *e = (class*) _afxExceptionLink.m_pException;
#undef END_CATCH
#define END_CATCH } else CppThrow( 0, FALSE); }}
#undef THROW
#define THROW(e) CppThrow( e, FALSE)
#undef THROW_LAST
#define THROW_LAST() CppThrow( 0, FALSE)
// Advanced macros for smaller code
#undef CATCH_ALL
// CATCH_ALL can only be the first handler in the list
#define CATCH_ALL(e) }} catch (CException* e) \
{ ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \
ASSERT( _afxExceptionLink.m_pException == e); \
CExceptionMonitor ExceptionMonitor; {
#undef AND_CATCH_ALL
#define AND_CATCH_ALL(e) \
} else { CException *e = _afxExceptionLink.m_pException;
#undef END_CATCH_ALL
#define END_CATCH_ALL }}}
#undef END_TRY
// END_TRY can only be the first handler in the list
#define END_TRY }} catch (CException* e) \
{ ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \
ASSERT( _afxExceptionLink.m_pException == e); \
CExceptionMonitor ExceptionMonitor; } }
// inline CExceptionMonitor member functions
inline CExceptionMonitor::~CExceptionMonitor() { Resume(); }
inline void CExceptionMonitor::Resume()
{
ASSERT( m_nCount >= 0);
if (! m_bResumed)
{
m_bResumed = TRUE;
if ( --m_nCount == 0 && m_pfCallback)
(*m_pfCallback)( FALSE);
}
ASSERT( m_nCount >= 0);
}
// simple hook chain facility ...
// provide your own dynamic unhooking or checking if needed
inline CExceptionMonitor::Callback
CExceptionMonitor::HookOnThrow( Callback newCallback)
{
Callback tmp = m_pfCallback;
m_pfCallback = newCallback;
return tmp;
}
#endif // CPP_EXCEPTIONS