// mainfrm.cpp : implementation of the CMainFrame class
//

#include "stdafx.h"
#include "except.h"
#include "mainfrm.h"

#include "sigcpp.h"  // combined setjmp.h & signal.h, modified for use with C++ 
#include <float.h>

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMainFrame

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
	//{{AFX_MSG_MAP(CMainFrame)
	ON_COMMAND(ID_SX_CRUNTIME_RAISE, OnSxRaise)
	ON_COMMAND(ID_SX_MFC_AFXTHROWXXXEXCEPTION, OnSxAfxthrowxxxexception)
	ON_COMMAND(ID_SX_MFC_TRYCATCHTHROW, OnSxTrycatchthrow)
	ON_COMMAND(ID_SX_WIN32API_RAISEEXCEPTION, OnSxRaiseexception)
	ON_COMMAND(ID_HX_CRUNTIME_SIGNAL, OnHxSetjmplongjmp)
	ON_COMMAND(ID_HX_CKEYWORDS_TRYEXCEPTFPDIVBYZERO, OnHxCkeywordsTryexceptFpdivbyzero)
	ON_COMMAND(ID_HX_CKEYWORDS_TRYEXCEPTINTDIVBYZERO,OnHxCkeywordsTryexceptIntdivbyzero)
	ON_COMMAND(ID_HX_CCKEYWORDS_TRYCATCHFPDIVBYZERO,OnHxCppkeywordsTryCatchFpdivbyzero)
	ON_COMMAND(ID_HX_CCKEYWORDS_TRYCATCHINTDIVBYZERO,OnHxCppkeywordsTryCatchIntdivbyzero)
	ON_COMMAND(ID_UX_FPDIVBYZERO, OnUxFpdivbyzero)
	ON_COMMAND(ID_UX_INTDIVBYZERO,OnUxIntdivbyzero)
	ON_COMMAND(ID_SX_CCKEYWORDS_TRYCATCHTHROW, OnSxCckeywordsTrycatchthrow)
	ON_COMMAND(ID_SX_CCKEYWORDS_TRYCATCHAFXTHROW, OnSxCckeywordsTrycatchafxthrow)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
	{
	//	To trap floating point exceptions under NT, use _controlfp().
	//	Reset the status bits in the exception handler with _clearfp().
	//
	int cw = ::_controlfp(0,0);
	cw &= ~(_EM_ZERODIVIDE | _EM_INVALID | _EM_DENORMAL | 
	   	    _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT);
	::_controlfp(cw, _MCW_EM);
	}

CMainFrame::~CMainFrame()
{
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	CFrameWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers

	
	
////////////////////////////////////////////////////////////////////////////////////////////
//
//    Exception handling using signal,setjmp,longjmp (and raise)
//
//
static jmp_buf setjmplongjmpBuffer;	// buffer for registers that longjmp will restore

extern "C" void SetjmpLongjmpSIGFPEHandler (int /*sig*/, int /*num*/)
	{
	_clearfp();
	longjmp (setjmplongjmpBuffer, -1);
	}
	
void CMainFrame::OnHxSetjmplongjmp()
	{
	//  step 1: install the exception handler for fp div by zero
	//    
	if ( signal(SIGFPE, (void (__cdecl *)(int, ...))::SetjmpLongjmpSIGFPEHandler) == SIG_ERR ) return;	                                   
	
	//  step 2: do a "try", "catch"
	//                    
	int iRet = ::setjmp (setjmplongjmpBuffer);	// here's where longjmp jumps to
	if (iRet == 0)
		{
		double x = 1.0;	//  "try"...
		x = x / 0.0f ;                                       
		::AfxMessageBox("Should never get here...exception not caught");
		}
	else  				//  "catch"...
		{				
		::AfxMessageBox("Hardware exception (fp divide by zero) trapped with signal,setjmp,longjmp");
		}
	}

void CMainFrame::OnSxRaise()
	{
	//  step 1: install the exception handler for fp div by zero
	//    
	if ( signal(SIGFPE, (void (__cdecl *)(int, ...))::SetjmpLongjmpSIGFPEHandler) == SIG_ERR ) return;	                                   
	
	//  step 2: do a "try", "catch"
	//                    
	int iRet = ::setjmp (setjmplongjmpBuffer);	// here's where longjmp jumps to
	if (iRet == 0)
		{
		raise(SIGFPE);
		::AfxMessageBox("Should never get here...exception not caught");
		}
	else  				//  "catch"...
		{				
		::AfxMessageBox("Software exception (raise) trapped with signal,setjmp,longjmp");
		}
	}

	
	  
///////////////////////////////////////////////////////////////////////////////////////////
//
//    Demonstrate exception handling using TRY, CATCH macros and AfxThrowXxxException
//
//
void CMainFrame::OnSxAfxthrowxxxexception()
	{
	TRY
		{
		CFile f("ohbaby", CFile::modeRead); // throws exception if "ohbaby" doesn't exist
		::AfxMessageBox("Should never get here...CFile exception not caught");
		}
	CATCH (CFileException, e)
		{
		CString sReason;
		switch (e->m_cause)
			{
			case CFileException::fileNotFound	: sReason = "file not found";	break;
			case CFileException::badPath		: sReason = "bad path";			break;
			default								: sReason = "unable to open file"; break;
			}
		CString s = "Software exception (CFileException - " + sReason + ") trapped with TRY, CATCH";
		::AfxMessageBox(s);
		}
	END_CATCH
	}

void MyBadFunction(){AfxThrowUserException();}
	
void CMainFrame::OnSxTrycatchthrow()
	{
	TRY
		{
		MyBadFunction(); // throws CUserException
		::AfxMessageBox("Should never get here...exception not caught");
		}
	CATCH (CUserException, e)
		{
		::AfxMessageBox("Software exception (AfxThrowUserException) trapped with TRY, CATCH");
		}
	END_CATCH
	}

	  
///////////////////////////////////////////////////////////////////////////////////////////
//
//    Demonstrate Structured Exception Handling (SEH) using C's __try, __except
//
//
void CMainFrame::OnHxCkeywordsTryexceptIntdivbyzero()
	{
	__try	
		{
		int x = 1;
		x = x / 0;                                       
		::AfxMessageBox("Should never get here...exception not caught");
		}
	__except (GetExceptionCode() ==  EXCEPTION_INT_DIVIDE_BY_ZERO ? 
									 EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)  				//  "catch"...
		{				
		::AfxMessageBox("Hardware exception (integer divide by zero) trapped with __try, __except");
		}
	}

void CMainFrame::OnHxCkeywordsTryexceptFpdivbyzero()
	{
	__try	
		{
		double x = 1.0;
		x = x / 0.0f ;                                       
		::AfxMessageBox("Should never get here...exception not caught");
		}
	__except (GetExceptionCode() ==  EXCEPTION_FLT_DIVIDE_BY_ZERO ? 
									 EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)  				//  "catch"...
		{
		_clearfp();				
		::AfxMessageBox("Hardware exception (fp divide by zero) trapped with __try, __except");
		}
	}

void CMainFrame::OnSxRaiseexception()
	{
	#define EXCEPTION_MYEXCEPTION 0xE0000001

	__try	
		{
		RaiseException(EXCEPTION_MYEXCEPTION, 0,0,0);
		::AfxMessageBox("Should never get here...exception not caught");
		}
	__except (GetExceptionCode() ==  EXCEPTION_MYEXCEPTION ? 
									 EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)  				//  "catch"...
		{				
		::AfxMessageBox("Software exception (EXCEPTION_MYEXCEPTION) trapped with __try, __except");
		}
	}

	  
///////////////////////////////////////////////////////////////////////////////////////////
//
//    Demonstrate NT's default exception handling.
//    Note that Dr Watson logs error and aborts app.
//
//
void CMainFrame::OnUxFpdivbyzero()
	{
	//	Generate an fp exception & let NT's default handler deal with it.
	//
	//	To trap floating point exceptions under NT, use _controlfp().
	//
	double x = 1.;
	x /= 0.;
	::AfxMessageBox("fp divide by zero exception not caught");	
	}

void CMainFrame::OnUxIntdivbyzero()
	{
	//	Generate an int div by zero exception & let default handler deal with it.
	//
	int x = 1;
	x /= 0;
	::AfxMessageBox("integer divide by zero exception not caught");	
	}


///////////////////////////////////////////////////////////////////////////////////////////
//
//    Demonstrate C++ try catch throw.
//  
//
//

void CMainFrame::OnHxCppkeywordsTryCatchFpdivbyzero()
	{
	try	
		{
		double x = 1.0;
		x = x / 0.0f ;                                    
		::AfxMessageBox("Should never get here...exception not caught");
		}
	catch (...)
		{
		_clearfp();				
		::AfxMessageBox("Hardware exception (fp divide by zero) trapped with try, catch");
		}
	}

void CMainFrame::OnHxCppkeywordsTryCatchIntdivbyzero()
	{
	try	
		{
		int x = 1;
		x = x / 0;                                       
		::AfxMessageBox("Should never get here...exception not caught");
		}
	catch (...)
		{				
		::AfxMessageBox("Hardware exception (integer divide by zero) trapped with try, catch");
		}
	}

void CMainFrame::OnSxCckeywordsTrycatchthrow()
	{
	try
		{
		throw "uh oh";
		::AfxMessageBox("Should never get here...exception not caught");
		}
	catch (char *)
		{
		::AfxMessageBox("Software exception (throw char*) trapped with try, catch");
		}
	}

void CMainFrame::OnSxCckeywordsTrycatchafxthrow()
	{
	try
		{
		CFile f("ohbaby", CFile::modeRead); // throws exception if "ohbaby" doesn't exist
		::AfxMessageBox("Should never get here...CFile exception not caught");
		}
	catch (.../*CFileException, e*/)
		{
		::AfxMessageBox("Software exception (AfxThrowFileException) trapped with try, catch");
		}

	}
