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   
Text File  |  1996-04-30  |  8KB  |  218 lines

  1. // redefafx.h
  2. // bug fixed by Vesely on 30 apr 96
  3. //
  4. // Arranged by Vesely in Milan from MFC 3.0 afx.h, which is an instance
  5. // of the Microsoft Foundation Classes C++ library, which is
  6. // Copyright (C) 1992 Microsoft Corporation
  7. //
  8. // This header file is included after <afx.h> in the "stdafx.h" header,
  9. // also in the one which is precompiled to build the MFC 2.52 class library.
  10. // The purpose of rebuilding the library is to take advantage of the
  11. // Exception Handling feature in a 16 bits compiler: the exception
  12. // handling macros are redefined in order to do real C++ exceptions,
  13. // instead of setjmp/longjmp.
  14. //
  15. // Note for upward compatibility
  16. // =============================
  17. // the macro redefinitions presented hereafter are similar to the
  18. // definitions used in MFC30. As defined below, one does step by
  19. // step unwinding, i.e. each try block on the call stack is visited.
  20. // In this respect, MFC30 is closer to the standard. MFC30 internally
  21. // redefines the macros to be even closer to the standard, and avoid
  22. // building AFX_EXCEPTION_LINK every time a TRY is entered. Handlers need
  23. // to use the DELETE_EXCEPTION/NO_CPP_EXCEPTION mutually exclusive macros.
  24. //
  25. // AFX_EXCEPTION_LINK usage can be avoided in MFC25 too, provided that
  26. // handlers code is upgraded to use DELETE_EXCEPTION for all CException-
  27. // derived exceptions that are build on the heap. (Notice that, obviously,
  28. // CMemoryException objects are NOT build on the heap.)
  29. // In that case, upgrade macros redefinitions accordingly,
  30. // i.e. not building and not asserting the AFX_EXCEPTION_LINKs.
  31. //
  32. // For using regular try/catch/throw statements instead of macros,
  33. // and still be compatible with code that uses the macros,
  34. // one must delete CExceptions in the handlers and arrange for OnThrow
  35. // to be called from the compiler-specific throw functions, the latter
  36. // being very unportable. A good compromise seems use try/catch,
  37. // but use macros or special functions for THROW, until the exception
  38. // monitor or equivalent functionality will possibly be standardized.
  39.  
  40. /////////////////////////////////////////////////////////////////////////////
  41. // Exception macros using try, catch and CppThrow
  42. // (source compatibile to versions 2.5x of MFC)
  43.  
  44. #if defined( CPP_EXCEPTIONS)
  45.  
  46. #if 1 // workaround for Symantec v 7.0r1 bug:
  47. // ~AFX_EXCEPTION_LINK is not called during stack unwinding
  48. // because it is a __near struct in a large memory model
  49. // remove the patch when the bug will be fixed
  50. class WorkaroundBug : public AFX_EXCEPTION_LINK
  51. {
  52. public:
  53.    ~WorkaroundBug() {}
  54. };
  55. #define AFX_EXCEPTION_LINK_ WorkaroundBug
  56. #else
  57. #define AFX_EXCEPTION_LINK_ AFX_EXCEPTION_LINK
  58. #endif // workaround for Symantec v 7.0r1 bug
  59.  
  60. // replacement for AfxThrow
  61. void AFXAPI CppThrow(CException* pException, BOOL bShared);
  62.  
  63. // after some thought, I've decided to keep the exception
  64. // monitor in the retail build, to enable destructors to test
  65. // if stack unwinding is currently being performed, before
  66. // possibly throwing an exception
  67.  
  68. class CExceptionMonitor
  69. {
  70. public:
  71.    typedef void(*Callback)( BOOL bStartUnwinding);
  72.  
  73. private:
  74.    static int m_nCount;
  75.    static Callback m_pfCallback;
  76.  
  77.    BOOL m_bResumed;
  78.  
  79.    friend void AFXAPI CppThrow(CException* pException,
  80.       BOOL bShared);      // calls here
  81.    static void OnThrow(); // just before each throw
  82.  
  83. public:
  84.    CExceptionMonitor() : m_bResumed( FALSE)
  85.    {
  86.       // there must be one auto object inside each handler's block,
  87.       // as done in the macro redefinitions below
  88.       ASSERT( m_nCount > 0);
  89.    }
  90.  
  91.    ~CExceptionMonitor();
  92.  
  93.    // manually called from a handler to mean the exception
  94.    // has been handled. Technically, the exception is
  95.    // handled as soon as the handler gets control.
  96.    // However, most handlers just do manual cleanup,
  97.    // so it seems meaningful to extend the critical zone.
  98.    void Resume();
  99.  
  100.    // can be tested in object destructors before throwing
  101.    static BOOL Unwinding() { ASSERT( m_nCount >= 0); return m_nCount; }
  102.  
  103.    // can be used to set a callback
  104.    static Callback HookOnThrow( Callback newCallback);
  105. };
  106.  
  107. #if defined( _DEBUG)
  108. class CDebugException : public CException
  109. // only CATCH_ALL/END_CATCH_ALL get this:
  110. // CATCH( CDebugException, e) => compile error in retail build
  111. {
  112.    DECLARE_DYNAMIC( CDebugException)
  113. public:
  114.    CDebugException();
  115. };
  116.  
  117. // this intermittently throws the relevant exception
  118. void ThrowPointTest( CRuntimeClass *pE, LPCSTR lpszFileName, int nLine);
  119.  
  120. #define EXCEPTIONS_CAN_BE_THROWN(e) \
  121.    ThrowPointTest( RUNTIME_CLASS( e), THIS_FILE, __LINE__)
  122. #else
  123. #define EXCEPTIONS_CAN_BE_THROWN(e) ((void)0)
  124. #endif // _DEBUG
  125.  
  126. #undef TRY
  127. #define TRY { AFX_EXCEPTION_LINK_ _afxExceptionLink; \
  128.    try { EXCEPTIONS_CAN_BE_THROWN( CDebugException); {
  129.  
  130. /////////////////////////////////////////////////////
  131. // BUG FIX: all the catch clauses are gathered under
  132. // a unique catch block, and the type of exception is
  133. // resolved on the catch side.
  134. // As dynamic_cast is not quite as robust as MFC's
  135. // IsKindOf, I use the latter.
  136.  
  137. // Note: this new arrangement makes it an error to do
  138. // AND_CATCH_ALL(E) /* something */ END_CATCH: must
  139. // use END_CATCH_ALL, as it was in MFC 2.x.
  140.  
  141.  
  142. #undef CATCH
  143. // CATCH can only be the first handler in the list:
  144. // in the (rare) case of a handler list with more than one
  145. // meaningful selective handler, EXCEPTIONS_CAN_BE_THROWN
  146. // needs to be coded explicitely.
  147. #define CATCH(class, e) EXCEPTIONS_CAN_BE_THROWN( class); } \
  148.         } catch (CException*) { \
  149.           CExceptionMonitor ExceptionMonitor; \
  150.           if ( _afxExceptionLink.m_pException-> \
  151.              IsKindOf( RUNTIME_CLASS( class))) \
  152.           { class *e = (class*) _afxExceptionLink.m_pException;
  153.  
  154. #undef AND_CATCH
  155. #define AND_CATCH(class, e) } else if \
  156.         ( _afxExceptionLink.m_pException->IsKindOf( RUNTIME_CLASS( class))) \
  157.         { class *e = (class*) _afxExceptionLink.m_pException;
  158.  
  159. #undef END_CATCH
  160. #define END_CATCH } else CppThrow( 0, FALSE); }}
  161.  
  162. #undef THROW
  163. #define THROW(e) CppThrow( e, FALSE)
  164.  
  165. #undef THROW_LAST
  166. #define THROW_LAST() CppThrow( 0, FALSE)
  167.  
  168. // Advanced macros for smaller code
  169. #undef CATCH_ALL
  170. // CATCH_ALL can only be the first handler in the list
  171. #define CATCH_ALL(e) }} catch (CException* e) \
  172.         { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \
  173.           ASSERT( _afxExceptionLink.m_pException == e); \
  174.           CExceptionMonitor ExceptionMonitor; {
  175.  
  176. #undef AND_CATCH_ALL
  177. #define AND_CATCH_ALL(e) \
  178.         } else { CException *e = _afxExceptionLink.m_pException;
  179.  
  180. #undef END_CATCH_ALL
  181. #define END_CATCH_ALL }}}
  182.  
  183. #undef END_TRY
  184. // END_TRY can only be the first handler in the list
  185. #define END_TRY }} catch (CException* e) \
  186.         { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \
  187.           ASSERT( _afxExceptionLink.m_pException == e); \
  188.           CExceptionMonitor ExceptionMonitor;  } }
  189.  
  190.  
  191. // inline CExceptionMonitor member functions
  192. inline CExceptionMonitor::~CExceptionMonitor() { Resume(); }
  193.  
  194. inline void CExceptionMonitor::Resume()
  195. {
  196.    ASSERT( m_nCount >= 0);
  197.  
  198.    if (! m_bResumed)
  199.    {
  200.       m_bResumed = TRUE;
  201.       if ( --m_nCount == 0 && m_pfCallback)
  202.          (*m_pfCallback)( FALSE);
  203.    }
  204.    ASSERT( m_nCount >= 0);
  205. }
  206.  
  207. // simple hook chain facility ...
  208. // provide your own dynamic unhooking or checking if needed
  209. inline CExceptionMonitor::Callback
  210. CExceptionMonitor::HookOnThrow( Callback newCallback)
  211. {
  212.    Callback tmp = m_pfCallback;
  213.    m_pfCallback = newCallback;
  214.    return tmp;
  215. }
  216.  
  217. #endif // CPP_EXCEPTIONS
  218.