home *** CD-ROM | disk | FTP | other *** search
- /*
- File: Except.h
-
- Contains: Exception handling macros
-
- Owned by: Jens Alfke
-
- Copyright: © 1993 - 1995 by Apple Computer, Inc., all rights reserved.
-
- */
-
-
- /*
- THEORY OF OPERATION
-
- This is a catch/throw based exception handling package which models
- much of the behavior of native C++ exception handling. (Its macros can
- be redefined to use native exceptions if your compiler supports them.)
-
- Reading this header is not recommended for the faint of heart! Here be
- gnarly macros, setjmp fu, and tangled #ifdefs.
- Please see the recipe document "Using Exceptions" for details presented
- in a human-readable fashion.
-
- If the symbol _NATIVE_EXCEPTIONS_ is predefined, native C++ exception
- handling will be used.
- If the symbol _ASM_XTRY_ is predefined, a special assembly-coded
- version of _xTry will be called, which makes the calling code for TRY
- shorter and slightly faster. (This feature still in progress...)
- */
-
- #ifndef _EXCEPT_
- #define _EXCEPT_
-
- #ifndef _ODTYPES_
- #include "ODTypes.h"
- #endif
-
- #ifndef FWODEXCE_H // [HLX]
- #include "FWODExce.h" // [HLX]
- #endif // [HLX]
-
- #ifndef _ERRORDEF_
- #ifdef __cplusplus
- #include "ErrorDef.xh" // Clients probably need the error codes as well
- #else
- #include "ErrorDef.h"
- #endif
- #endif
-
- #ifndef __SETJMP__
- #include <setjmp.h>
- #endif
-
- #ifdef __LIBRARYMANAGER__
- #error "Please don't include both Except.h and LibraryManager.h"
- #endif
-
-
- #ifdef _OD_IMPL_SHARE_UTILS_
- #pragma import on
- #endif
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
-
- //=====================================================================================
- // ODVolatile
- //=====================================================================================
-
- // Any variable or parameter that is modified in a TRY block and used in the
- // CATCH block must be declared as volatile or it may have an incorrect value
- // in the CATCH block.
- // Since not all compilers support the 'volatile' keyword, use this instead;
-
- #ifndef _NATIVE_EXCEPTIONS_
- #define ODVolatile(x) ((void) &x)
- #else
- #define ODVolatile(x) /*no need for this with native exceptions*/
- #endif
-
- //=====================================================================================
- // Exception Handling Macros (native C++ exceptions)
- //=====================================================================================
-
- #ifdef _NATIVE_EXCEPTIONS_
-
- #define ErrorCode() (_exception.error)
- #define ErrorMessage() (_exception.message)
- #define SetErrorCode(ERR) (_exception.error=(ERR))
- #define SetErrorMessage(MSG) (strcpy(_exception.error,(MSG))
-
- #define TRY \
- try {
-
- #define CATCH_ALL \
- } catch(ODException _exception) {
-
- #define RERAISE \
- throw
-
- #define SET_SOM_EXCEPTION(EV) \
- ODSetSOMException(EV,_exception)
-
- void _xSetSOMException(Environment*,ODException&);
-
- #define ENDTRY \
- }
-
- /* CATCH( ) will not work with native exceptions. Don't use it! */
-
-
- //=====================================================================================
- // Exception Handling Macros (emulated)
- //=====================================================================================
-
- #else /*not _NATIVE_EXCEPTIONS*/
-
- //#define ErrorCode() (_except.fError) // [HLX]
- #define ErrorCode() (_except.GetPlatformError()) // [HLX]
-
- //#define ErrorMessage() (_except.fODException ?_except.fODException->message :kODNULL) // [HLX]
- #define ErrorMessage() (kODNULL) // [HLX]
-
- #define SetErrorCode(ERR) (_xSetErrorCode(&_except,(ERR))) // [HLX] Jim, what should we do?
- #define SetErrorMessage(MSG) (_xSetErrorMessage(&_except,(MSG)) // [HLX] Jim, what should we do?
-
- #ifndef _ASM_XTRY_
- #define _setjmp_xTry(EX) setjmp(*_xTry(EX))
- #define _setjmp_xTryEv(EX,EV) setjmp(*_xTryEv(EX,EV))
- #endif
-
- #define TRY FW_TRY // [HLX]
- /* // [HLX]
- #define TRY \
- { \
- ODExceptionFrame _except; \
- ODVolatile(_except); \
- if (_setjmp_xTry(&_except) == 0) \
- {
- */ // [HLX]
-
- #define CATCH_ALL FW_CATCH_BEGIN FW_CATCH_REFERENCE(FW_XException, _except) // [HLX]
- /* // [HLX]
- #define CATCH_ALL \
- } \
- else \
- {
- */ // [HLX]
-
-
- #define RERAISE FW_THROW_SAME() // [HLX]
- /* // [HLX]
- #define RERAISE \
- _xReraise(&_except)
- */ // [HLX]
-
- #define SET_SOM_EXCEPTION(EV) \
- _xSetSOMException(EV,&_except)
-
- #define ENDTRY FW_CATCH_END // [HLX]
- /* // [HLX]
- #ifdef __cplusplus
- #define ENDTRY \
- } \
- }
- #else // C version:
- #define ENDTRY \
- } \
- _xPop(&_except); \
- }
- #endif
- */ // [HLX]
-
- // CATCH( ) is not compatible with native C++ exceptions.
- // Its use is discouraged.
- //#define CATCH(e) \
- // } else if (_except.fError==(e)) {
-
-
- #endif /*_NATIVE_EXCEPTIONS*/
-
- //=====================================================================================
- // Raising Exceptions
- //=====================================================================================
-
- //void THROW(ODError error); // [HLX]
- //void THROW_IF_ERROR(ODError error); // [HLX]
- //void THROW_IF_NULL(void* value); // [HLX]
-
- inline void THROW(ODError error)
- {FW_Failure(error); }
- inline void THROW_IF_ERROR(ODError error)
- {FW_FailOnError(error); }
- inline void THROW_IF_NULL(void* value)
- {if (!value) FW_Failure(kODErrOutOfMemory); }
-
- // Optional message parameters (ignored in nondebug build):
- #if ODDebug
- void THROW_IF_ERROR_M(ODError error, const char* msg);
- void THROW_M(ODError error, const char* msg);
- void THROW_IF_NULL_M(void* value, const char* msg);
- #else
- #define THROW_IF_ERROR_M(ERR,MSG) THROW_IF_ERROR(ERR)
- #define THROW_M(ERR,MSG) THROW(ERR)
- #define THROW_IF_NULL_M(ERR,MSG) THROW_IF_NULL(ERR)
- #endif
-
- #ifdef __cplusplus
- }
- // Overloaded C++ equivalents:
- inline void THROW_IF_ERROR(ODError error, const char* /*msg*/) // [HLX]
- {THROW_IF_ERROR_M(error,msg);}
- inline void THROW(ODError error, const char* /*msg*/) // [HLX]
- {THROW_M(error,msg);}
- inline void THROW_IF_NULL(void* value, const char* /*msg*/) // [HLX]
- {THROW_IF_NULL_M(value,msg);}
- inline void THROW_IF_NULL(void* value, ODError error)
- {if ( value == kODNULL ) THROW(error);}
- extern "C" {
- #endif
-
- // Call BreakOnThrow(TRUE) to break into the debugger whenever THROW is called.
- // (The call returns the previous value of the setting.)
- ODBoolean BreakOnThrow( ODBoolean brk );
-
-
- //=====================================================================================
- // SOM Exception Utilities
- //=====================================================================================
-
- // This modified TRY block should be used in SOM methods. It's just like a
- // regular TRY...CATCH_ALL...ENDTRY except that the exception code will be
- // stored in the Environment. Needless to say you should _not_ reraise!
- // You should also not make any SOM calls after the SOM_ENDTRY, nor declare any
- // Destructo objects before the SOM_TRY.
-
- #ifdef _NATIVE_EXCEPTIONS_
-
- #define SOM_TRY \
- TRY
-
- #define SOM_CATCH_ALL \
- CATCH_ALL { \
-
- #define SOM_ENDTRY \
- } ODSetSOMException(ev,_exception); \
- ENDTRY
-
- #else /*not _NATIVE_EXCEPTIONS_*/
-
- #define SOM_TRY \
- { \
- ODExceptionFrame _except; \
- ODVolatile(_except); \
- if (_setjmp_xTryEv(&_except,ev) == 0) \
- {
-
- #define SOM_CATCH_ALL \
- CATCH_ALL
- #define SOM_ENDTRY \
- ENDTRY
-
- #endif /*_NATIVE_EXCEPTIONS_*/
-
-
- // ODSetSOMException stores an OD error code in the environment.
- // ODGetSOMException returns the OD error code (if any) from an environment.
-
- #ifdef __cplusplus
- void ODSetSOMException( Environment*, ODError, const char *msg =kODNULL );
- #else
- void ODSetSOMException( Environment*, ODError, const char *msg );
- #endif
-
- #ifdef _NATIVE_EXCEPTIONS_
- } // end extern C
- void ODSetSOMException( Environment*, ODException& );
- extern "C" {
- #endif
-
- ODError ODGetSOMException( Environment *ev );
-
- // CHECK_ENV throws an exception if the environment indicates an error.
-
- void CHECK_ENV( Environment* );
-
- // SOMCHKEXCEPT is a macro that is called in a .xh file if the ev variable
- // indicates an exception is set.
- //#define SOMCHKEXCEPT {CHECK_ENV(ev);} [HLX]
-
-
- //=====================================================================================
- // Obsolete Exception Utilities
- //=====================================================================================
-
- /* FN_CATCH and SOM_CATCH are discouraged (not compatible with native C++
- exceptions) but still implemented for the time being to give people time
- to convert their code. */
-
- #if defined(__MWERKS__) || defined(__SC__)
- extern void FN_CATCH_DIDNT_RETURN( );
- /* This function is purposely declared but never defined. Due to the setup of
- the for loop in FN_CATCH and SOM_CATCH, a failure to end the block with a
- return statement will cause the call to FN_CATCH_DIDNT_RETURN not to be
- dead stripped, resulting in a link error. This will help catch this nasty
- coding error. */
- #else
- // Other compilers may not dead-strip properly.
- #define FN_CATCH_DIDNT_RETURN() /**/
- #endif
-
- #define FN_CATCH \
- ODExceptionFrame _except; \
- ODVolatile(_except); \
- if (_setjmp_xTry(&_except) != 0) \
- for( ; true; FN_CATCH_DIDNT_RETURN() )
-
- #define SOM_CATCH \
- ODExceptionFrame _except; \
- ODVolatile(_except); \
- if (_setjmp_xTryEv(&_except,ev) != 0) \
- for( ; true; FN_CATCH_DIDNT_RETURN() )
-
-
- //=====================================================================================
- // Finally, the Exception Handler (ODExceptionFrame struct)
- //=====================================================================================
-
-
- #ifndef _NATIVE_EXCEPTIONS_
-
- #ifdef __cplusplus
- class Destructo; // forward declarations for use below
- struct ODExceptionFrame;
- void _xPop(ODExceptionFrame*);
- } // end of extern "C" block
- #else
- typedef struct ODExceptionFrame ODExceptionFrame;
- typedef struct Destructo Destructo; // Not used in C but must declare anyway
- #endif
-
- struct ODExceptionFrame
- {
- ODExceptionFrame* fPrev;
- ODException* fODException;
- ODError fError;
- Environment* fEv;
- Destructo* fDestructoList;
- jmp_buf fBuffer;
- // If you change the size of this struct you _must_ update Except.s and Except.a
- // accordingly!
- #ifdef __cplusplus
- void Throw( ODError err, const char* msg, ODException *x =kODNULL );
- inline ~ODExceptionFrame( ) {_xPop(this);}
- #endif
- };
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- typedef struct ODExceptionFrame ODExceptionFrame;
-
- #ifdef _ASM_XTRY_
- int _setjmp_xTry( ODExceptionFrame* );
- int _setjmp_xTryEv( ODExceptionFrame*, Environment* );
- #else
- jmp_buf* _xTry( ODExceptionFrame* );
- jmp_buf* _xTryEv( ODExceptionFrame*, Environment* );
- #endif
-
- void _xReraise( ODExceptionFrame* );
- void _xSetSOMException(Environment*,ODExceptionFrame*);
- void _xPop( ODExceptionFrame* );
- void _xSetErrorCode( ODExceptionFrame*, ODError );
- void _xSetErrorMessage( ODExceptionFrame*, const char* );
-
- #endif /*_NATIVE_EXCEPTIONS_*/
-
-
- #ifdef __cplusplus
- } // end of extern "C" block
- #endif
-
-
- //=====================================================================================
- // Destructo, a C++ base class for auto-destruct objects
- //=====================================================================================
-
- #ifdef __cplusplus
-
- class Destructo
- {
- //#ifndef _NATIVE_EXCEPTIONS_ // [HLX]
- protected:
- Destructo( ) {};// [HLX]
-
- public:
- virtual ~Destructo( ){};// [HLX]
-
- private:
- Destructo* EmergencyDestruct( ){return this;};// [HLX]
- Destructo *fPrevDestructo;
- friend class ODExceptionFrame;
-
- //#endif /*_NATIVE_EXCEPTIONS_*/ // [HLX]
- static void* operator new( size_t ); // Make it illegal to allocate on heap
- // In future could use alloca??
-
- private: // disallow these:
- Destructo(const Destructo& );
- void operator=(const Destructo& );
- // Bitwise assigning one destructo to another smashes
- // fPrevDestructo with potentially unpleasant effects.
- };
-
- #endif /*__cplusplus*/
-
- #ifdef _OD_IMPL_SHARE_UTILS_
- #pragma import off
- #endif
-
-
- #endif // _EXCEPT_
-