home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-08 | 13.6 KB | 422 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWExcRun.cpp
- // Release Version: $ 1.0d11 $
- //
- // Copyright: (c) 1993, 1995 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFound.hpp"
-
- #ifndef FW_NATIVE_EXCEPTIONS
-
- #include <stdlib.h>
- #include <string.h>
-
- #ifndef FWEXCRUN_H
- #include "FWExcRun.h"
- #endif
-
- #ifndef FWDELSTA_H
- #include "FWDelSta.h"
- #endif
-
- #ifndef FWTRYBLO_H
- #include "FWTryBlo.h"
- #endif
-
- #ifndef FWPRIDEB_H
- #include "FWPriDeb.h"
- #endif
-
- #ifndef FWPRIMEM_H
- #include "FWPriMem.h"
- #endif
-
- #ifndef FWNEWHEL_H
- #include "FWNewHel.h"
- #endif
-
- #ifndef FWONSTAC_H
- #include "FWOnStac.h"
- #endif
-
- #if defined FW_BUILD_WIN && defined __BORLANDC__
- #include <except.h>
- #endif
-
- #if FW_LIB_EXPORT_PRAGMAS
- #pragma lib_export on
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment FWExcLib
- #endif
-
- //========================================================================================
- // Functions for "unexpected" and "terminate"
- //
- // See ARM, Section 15.6
- //========================================================================================
-
- static void DefaultTerminate();
- static void DefaultUnexpected();
-
- static void DefaultTerminate()
- {
- abort();
- }
-
- static void DefaultUnexpected()
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- PFV pfCurrentTerminate = globals.gCurrentTerminate;
- (*pfCurrentTerminate)();
- }
-
- #if !defined(__BORLANDC__) && !defined(__MWERKS__)
- void terminate()
- {
- FW_PRIV_DEBUGGER_BREAK();
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- PFV pfCurrentTerminate = globals.gCurrentTerminate;
- (*pfCurrentTerminate)();
- }
-
- void unexpected()
- {
- FW_PRIV_DEBUGGER_BREAK();
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- PFV pfCurrentUnexpected = globals.gCurrentUnexpected;
- (*pfCurrentUnexpected)();
- }
-
- PFV set_terminate(PFV terminate)
- {
- return FW_CPrivExceptionRuntime::SetTerminate(terminate);
- }
-
- PFV set_unexpected(PFV unexpected)
- {
- return FW_CPrivExceptionRuntime::SetUnexpected(unexpected);
- }
- #endif
-
- #ifdef FW_BUILD_WIN32
- int _FW_PrivIsOnStack(void * p)
- {
- // [KVV] This version of IsOnStack assumes that the stack is only 16K.
- // In reality, Windows NT allocates a much larger stack.
-
- char localVar;
- return (&localVar < p) && (p <= &localVar + 16000);
- }
- #endif
-
- #if GENERATINGCFM
- int _FW_PrivIsOnStack(void * p)
- {
- char localVar;
- return (&localVar < p) && (p < LMGetCurStackBase());
- }
- #endif
-
- #ifdef __MWERKS__
-
- const FW_CPrivNewHelper& _FW_MetrowerksHack(const FW_CPrivNewHelper&);
-
- const FW_CPrivNewHelper& _FW_MetrowerksHack(const FW_CPrivNewHelper& helper)
- {
- return helper;
- }
-
- #endif
-
- //========================================================================================
- // CLASS FW_CPrivExceptionRuntime
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::Initialize
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::Initialize(FW_SPrivExceptionGlobals& globals)
- {
- globals.gExceptionBufferSize = kDefaultExceptionBufferSize;
- globals.gExceptionBuffer = ::FW_PrimitiveAllocateBlock(kDefaultExceptionBufferSize);
- globals.gCurrentTerminate = DefaultTerminate;
- globals.gCurrentUnexpected = DefaultUnexpected;
-
- #ifdef FW_DEBUG
- SetBreakOnThrow(NULL);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::Terminate
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::Terminate()
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- ::FW_PrimitiveFreeBlock(globals.gExceptionBuffer);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::SetTerminate
- //----------------------------------------------------------------------------------------
- PFV FW_CPrivExceptionRuntime::SetTerminate(PFV newTerminate)
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- PFV oldTerminate = globals.gCurrentTerminate;
- globals.gCurrentTerminate = newTerminate;
- return oldTerminate;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::SetUnexpected
- //----------------------------------------------------------------------------------------
- PFV FW_CPrivExceptionRuntime::SetUnexpected(PFV newUnexpected)
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- PFV oldUnexpected = globals.gCurrentUnexpected;
- globals.gCurrentUnexpected = newUnexpected;
- return oldUnexpected;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::CaughtException
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::CaughtException(FW_SPrivExceptionGlobals& globals, _FW_XException * caughtException)
- {
- globals.gThrownException->PrivDelete();
- globals.gCaughtException = caughtException;
- globals.gThrownException = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::CaughtEverythingException
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::CaughtEverythingException(FW_SPrivExceptionGlobals& globals)
- {
- globals.gCaughtException = globals.gThrownException;
- globals.gThrownException = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::CaughtNoInstanceException
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::CaughtNoInstanceException(FW_SPrivExceptionGlobals& globals)
- {
- globals.gCaughtException = globals.gThrownException;
- globals.gThrownException = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::CaughtReferenceException
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::CaughtReferenceException(FW_SPrivExceptionGlobals& globals)
- {
- globals.gCaughtException = globals.gThrownException;
- globals.gThrownException = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::PrimitiveThrow
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivExceptionRuntime::PrimitiveThrow(const _FW_XException & thrownException)
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
-
- // Should never have an exception on the way in
- FW_PRIV_ASSERT(globals.gThrownException == NULL);
-
- FW_CPrivTryBlockContext *context = globals.gCurrentContext;
- FW_PRIV_ASSERT(context!=NULL);
- if (context->fPriorContext == NULL)
- {
- terminate();
- abort(); // Terminate should never return
- }
-
- if (FW_CPrivDeleteStack::IsClassExpectedInContext(context, thrownException.PrivVirtualGetClassInfo()))
- {
- // If someone had caught an exception delete that exception
- // because we are going to bypass the destructor for it.
- if (globals.gCaughtException != NULL)
- {
- globals.gCaughtException->PrivDelete();
- globals.gCaughtException = 0;
- }
-
- // Copy the original into our exception buffer
- thrownException.Copy(globals.gExceptionBuffer, globals.gExceptionBufferSize);
-
- // We have a thrown exception so point gThrownException at it.
- globals.gThrownException = (_FW_XException*)globals.gExceptionBuffer;
-
- // We have copied the original so delete it.
- ((_FW_XException &)thrownException).PrivDelete();
-
- DeleteObjectsInContextAndJump(globals, context);
- }
- else
- {
- unexpected();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::PrimitiveThrowSame
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivExceptionRuntime::PrimitiveThrowSame()
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
-
- FW_PRIV_ASSERT(globals.gCaughtException != NULL);
- if (globals.gCaughtException == NULL)
- {
- abort(); // Can't throwsame if nothing is currently caught
- }
-
- FW_CPrivTryBlockContext * context = globals.gCurrentContext;
- FW_PRIV_ASSERT(context != NULL);
- if (context->fPriorContext == NULL)
- {
- terminate();
- abort(); // Terminate should never return but if it does we will abort
- }
-
- _FW_XException *caughtException = globals.gCaughtException;
-
- if (FW_CPrivDeleteStack::IsClassExpectedInContext(context, caughtException->PrivVirtualGetClassInfo()))
- {
- if (caughtException != (_FW_XException *)globals.gExceptionBuffer)
- {
- // The exception is in the stack frame so copy it to our exception buffer,
- // delete the original and then pass the copy along.
- caughtException->Copy(globals.gExceptionBuffer, globals.gExceptionBufferSize);
- caughtException->PrivDelete();
- globals.gThrownException = (_FW_XException*)globals.gExceptionBuffer;
- }
- else
- {
- // The exception is already in our buffer
- globals.gThrownException = (_FW_XException*)globals.gCaughtException;
- }
-
- globals.gCaughtException = 0;
-
- DeleteObjectsInContextAndJump(globals, context);
- }
- else
- {
- unexpected();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::Throw
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::Throw(const _FW_XException & thrownException)
- {
- PrimitiveThrow(thrownException);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::ThrowSame
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::ThrowSame()
- {
- PrimitiveThrowSame();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::ThrowConstructor
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::ThrowConstructor(_FW_XException & thrownException)
- {
- PrimitiveThrow(thrownException);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::ThrowSameConstructor
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::ThrowSameConstructor()
- {
- PrimitiveThrowSame();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::KeepThrowing
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::KeepThrowing(FW_SPrivExceptionGlobals& globals)
- {
- FW_CPrivTryBlockContext *context = globals.gCurrentContext;
- FW_PRIV_ASSERT(context!=NULL);
- if (FW_CPrivDeleteStack::IsClassExpectedInContext(context, globals.gThrownException->PrivVirtualGetClassInfo()))
- {
- DeleteObjectsInContextAndJump(globals, context);
- }
- else
- {
- unexpected();
- }
- }
-
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::ResetExceptionBufferSize
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::ResetExceptionBufferSize(size_t newSize)
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- void *p = ::FW_PrimitiveResizeBlock(globals.gExceptionBuffer, newSize);
- FW_PRIV_ASSERT(p != NULL);
- globals.gExceptionBuffer = p;
- globals.gExceptionBufferSize = newSize;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::DeleteObjectsInContextAndJump
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::DeleteObjectsInContextAndJump(FW_SPrivExceptionGlobals& globals,
- FW_CPrivTryBlockContext * context)
- {
- #ifdef FW_DEBUG
- _FW_XException *thrownException = globals.gThrownException;
- FW_ClassInfoPtr breakExceptionKind = globals.gBreakExceptionKind;
- if (breakExceptionKind!=NULL && thrownException->PrivIsKindOf(breakExceptionKind))
- FW_PRIV_DEBUGGER_STRING("Throwing an exception");
- #endif
-
- FW_CPrivDeleteStack::PopOffAndDeleteObjectsInContext(globals, context);
-
- jmp_buf *jumpBuffer = context->fJumpBuffer;
- // context->FW_CPrivTryBlockContext::~FW_CPrivTryBlockContext();
- context->~FW_CPrivTryBlockContext();
- ::longjmp(*jumpBuffer, 1);
- }
-
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivExceptionRuntime::EndConstructor
- //----------------------------------------------------------------------------------------
- void FW_CPrivExceptionRuntime::EndConstructor(_FW_CAutoDestructObject *object, size_t size)
- {
- if (_FW_PrivIsOnStack(object))
- FW_CPrivDeleteStack::Push(object);
-
- #ifdef FW_USE_NEW_HELPER
- else
- {
- FW_CPrivNewHelper *helper = FW_CPrivNewHelper::TopNewHelper();
- if (helper!=NULL && helper->IsWatching(object))
- helper->UpdateForEndConstructor(object, size);
- }
- #endif
- }
-
- #endif // FW_NATIVE_EXCEPTIONS
-