#ifndef BREXCLIB_H
#define BREXCLIB_H
//========================================================================================
//
//     File:			BRExcLib.h
//     Release Version:	$ 1.0d1 $
//
//     Creation Date:	June 1, 1992
//
//     COPYRIGHT 1992-93 SYMANTEC CORPORATION. ALL RIGHTS RESERVED. UNPUBLISHED -- RIGHTS
//     RESERVED UNDER THE COPYRIGHT LAWS OF THE UNITED STATES. USE OF COPYRIGHT NOTICE IS
//     PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION OR DISCLOSURE.
//
//     THIS SOFTWARE CONTAINS PROPRIETARY AND CONFIDENTIAL INFORMATION OF SYMANTEC
//     CORPORATION. USE, DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR
//     EXPRESS WRITTEN PERMISSION OF SYMANTEC CORPORATION.
//
//     RESTRICTED RIGHTS LEGEND
//     Use, duplication, or disclosure by the Government is subject to restrictions as set
//     forth in subparagraph (c)(l)(ii) of the Rights in Technical Data and Computer
//     Software clause at DFARS 252.227-7013. Symantec Corporation, 10201 Torre Avenue,
//     Cupertino, CA 95014.
//
//========================================================================================

#ifndef   BRONSTAC_H
#include "BrOnStac.h"
#endif

#if defined(BR_DEBUG) && !defined(BRTRACE_H)
#include "BRTrace.h"
#endif

#ifndef   BRAUTODE_H
#include "BRAutoDe.h"
#endif

#ifndef   BRMETACL_H
#include "BRMetaCl.h"
#endif

#ifndef   BREXCEPT_H
#include "BRExcept.h"
#endif

#ifndef   BRTRYBLO_H
#include "BRTryBlo.h"
#endif

#ifndef   BREXCRUN_H
#include "BRExcRun.h"
#endif

#ifndef   BRDELSTA_H
#include "BRDelSta.h"
#endif

#if !defined(BREXCLOG_H) && defined(BR_DEBUG)
#include "BRExcLog.h"
#endif

#if !defined(BRNEWHEL_H) && defined(BR_USE_NEW_HELPER)
#include "BRNewHel.h"
#endif

#ifdef BR_BAD_CODE_GENERATION
int ReturnFalse();
int ReturnTrue();
#define BR_BEL_FALSE ::ReturnFalse()
#define BR_BEL_TRUE ::ReturnTrue()
#else
#define BR_BEL_FALSE 0
#define BR_BEL_TRUE 1
#endif

//========================================================================================
// Exception Handling Interface Macros
//========================================================================================

#define BR_VOLATILE(a) ((void) &a)
#define BR_DUMMY_RETURN_TRUE return 1;

#ifndef BR_DISABLE_BEL


#ifdef BR_USE_NEW_HELPER	
#define BR_NEW(class, args) (class*)								\
		(															\
		new(__BR_CBedNewHelper()) class##args, 						\
		(void*) __BR_CBedNewHelper::PopNewHelper()->ForgetObject()	\
		)
#else
#define BR_NEW(class, args) new class##args
#endif

#ifdef BR_DEBUG
// These two defines are solely to make the code immediately below more readable
#define BR_SAVE_TRACE_STATE unsigned short __traceDepth = _BR_CTraceRuntime::GetTraceDepth();
#define BR_RESTORE_TRACE_STATE _BR_CTraceRuntime::SetTraceDepth(__traceDepth);
#else
#define BR_SAVE_TRACE_STATE 
#define BR_RESTORE_TRACE_STATE 
#endif

#define BR_TRY \
	{ \
		BR_SAVE_TRACE_STATE \
		jmp_buf	__jumpBuffer; \
		if(setjmp(__jumpBuffer) == 0) \
		{ \
			_BR_CTryBlockContext __context(__jumpBuffer);

#define BR_CATCH_BEGIN \
		} \
		else \
		{ \
			BR_RESTORE_TRACE_STATE \
			if (BR_BEL_FALSE) \
			{

#define BR_CATCH(class, error) \
			} \
			else if (_BR_CExceptionRuntime::GetThrownException()->__IsKindOf(_BR_CLASS_REFERENCE(class))) \
			{ \
				class error = * (class*) _BR_CExceptionRuntime::GetThrownException(); \
				_BR_CExceptionRuntime::CaughtException(&error);

#define BR_CATCH_REFERENCE(class, error) \
			} \
			else if (_BR_CExceptionRuntime::GetThrownException()->__IsKindOf(_BR_CLASS_REFERENCE(class))) \
			{ \
				class & error = *(class*) _BR_CExceptionRuntime::GetThrownException(); \
				_BR_CExceptionRuntime::CaughtReferenceException();

#define BR_CATCH_NO_INSTANCE(class) \
			} \
			else if (_BR_CExceptionRuntime::GetThrownException()->__IsKindOf(_BR_CLASS_REFERENCE(class))) \
			{ \
				_BR_CExceptionRuntime::CaughtNoInstanceException();

#define BR_CATCH_EVERYTHING() \
			} \
			else if (BR_BEL_TRUE) \
			{ \
				_BR_CExceptionRuntime::CaughtEverythingException();

#define BR_CATCH_END \
			} \
			else \
			{ \
				_BR_CExceptionRuntime::KeepThrowing(); \
			} \
		_BR_CExceptionRuntime::CatchCleanup(); \
		} \
	}

#define BR_THROW(error) \
	_BR_CExceptionRuntime::Throw(error)

#define BR_THROW_SAME() \
	_BR_CExceptionRuntime::ThrowSame()

#define BR_THROWS_NOTHING() \
	_BR_SThrowGuard __nothing

#define BR_THROWS(class) \
	_BR_SThrowGuard __nothing##class(_BR_CLASS_REFERENCE(class))

#ifdef BR_USE_NEW_HELPER	
#define BR_END_CONSTRUCTOR \
	if (__OnStack(this)) \
		_BR_CDeleteStack::Push(this); \
	else \
		__BR_CBedNewHelper::TopNewHelper()->UpdateForEndConstructor(this, sizeof(*this));
#else
#define BR_END_CONSTRUCTOR \
	if (__OnStack(this)) \
		_BR_CDeleteStack::Push(this);
#endif

#define BR_START_DESTRUCTOR \
	if (__OnStack(this)) \
		_BR_CDeleteStack::PopIfTopEquals(this);



#else
	// This is how to turn exceptions off

	#define BR_TRY \
	{ \
		if(BR_BEL_TRUE) \
		{

	#define BR_CATCH_BEGIN \
		} \
		else \
		{ \
			if (BR_BEL_FALSE) \
			{
	
	#define BR_CATCH(class, error) \
			} \
			else if (BR_BEL_FALSE) \
			{ \
				class error = * (class*) 0;

	#define BR_CATCH_REFERENCE(class, error) \
			} \
			else if (BR_BEL_FALSE) \
			{ \
				class & error = *(class*) 0;
					
	#define BR_CATCH_NO_INSTANCE(class) \
			} \
			else if (BR_BEL_FALSE) \
			{

	#define BR_CATCH_EVERYTHING() \
			} \
			else if (BR_BEL_TRUE) \
			{

	#define BR_CATCH_END \
			} \
			else \
			{ \
			} \
		} \
	}

	#define BR_THROW(error) BR_PrimitiveDebuggerString(#error)
	#define BR_THROW_SAME()
	#define BR_THROWS_NOTHING()
	#define BR_THROWS(class)

	#define BR_END_CONSTRUCTOR
	#define BR_START_DESTRUCTOR
	#define BR_NEW(class, args) new class##args
#endif

//========================================================================================
// Exception Logging Macros
//========================================================================================

#ifdef BR_DEBUG
#define BR_LOG_OR_TRIGGER_EXCEPTION(class, instance) \
	if (_BR_CExceptionLog::GetLogEnableCount()) { \
		_BR_CExceptionLog::LogException(_BR_CLASS_REFERENCE(class)); \
	} \
	else { \
		_BR_CExceptionLog::TriggerException(_BR_CLASS_REFERENCE(class), instance); \
	}
#define BR_CAUSE_EXCEPTION_BY_NAME(name) _BR_CExceptionLog::CauseException(_BR_CLASS_REFERENCE(name))
#else
#define BR_LOG_OR_TRIGGER_EXCEPTION(class, instance) if (0) BR_THROW(instance)
#define BR_CAUSE_EXCEPTION_BY_NAME(name) ((void) 0)
#endif

//========================================================================================
// Exception Debugging Macros
//========================================================================================

#ifdef BR_DEBUG
#define BR_BREAK_ON_THROW(class) _BR_CExceptionRuntime::SetBreakOnThrow(_BR_CLASS_REFERENCE(class))
#define BR_NO_BREAK_ON_THROW	  _BR_CExceptionRuntime::SetBreakOnThrow(NULL)
#define BR_EXCEPTION_BREAK_CONTEXT(class) BR_CExceptionBreakContext __BreakContext(_BR_CLASS_REFERENCE(class))
#else
#define BR_BREAK_ON_THROW(class) 
#define BR_NO_BREAK_ON_THROW	  
#define BR_EXCEPTION_BREAK_CONTEXT(class) 
#endif

#endif
