headers/LibraryManager.h

/*  File:       LibraryManager.h
 
    Contains:   Minimal declarations you need to use the ASLM.
 
    Copyright:  © 1991-1995 by Apple Computer, Inc., all rights reserved.
 
 
*/
 
#ifndef __LIBRARYMANAGER__
#define __LIBRARYMANAGER__
 
#ifndef __STDDEF__
#include <stddef.h>
#endif
#ifndef __STRING__
#include <string.h>
#endif
#ifndef __TYPES__
#include <Types.h>
#endif
#ifndef __CONDITIONALMACROS__
#include <ConditionalMacros.h>
#endif
 
//
// Setup GENERATINGPOWERPC and GENERATING68K variables
//
#ifndef GENERATINGPOWERPC
    #if defined(powerc) || defined(__powerc)
        #define GENERATINGPOWERPC   1
    #else
        #define GENERATINGPOWERPC   0
    #endif
#endif
#ifndef GENERATING68K
    #if defined(powerc) || defined(__powerc)
        #define GENERATING68K       0
    #else
        #define GENERATING68K       1
    #endif
#endif
 
#ifndef GENERATINGCFM
    #define GENERATINGCFM   GENERATINGPOWERPC
#endif
 
//
//  Define the macros that handle adding an empty vtable slot at
//  the beginning of the vtable for SCpp.
//
#define ASLM_COMPATIBLE
#define ASLM_SCDECLARATION(className)
#if defined(__SC__) || defined(THINK_CPLUS) || defined(__MRC__)
    #if !NoDummyVTableSlot
        #undef ASLM_COMPATIBLE
        #undef ASLM_SCDECLARATION
        #define ASLM_COMPATIBLE                             \
            private:                                        \
                virtual     void DummyVirtualFunction();
                
        #define ASLM_SCDECLARATION(className)       \
        void className::DummyVirtualFunction() {}
    #endif
#endif
 
//
//  Define SINGLEOBJECT to true if the compiler support SingleObject.
//
#if GENERATING68K && !defined(__SC__) || defined(__MWERKS__)
    #define SINGLEOBJECT    1
#else
    #define SINGLEOBJECT    0
#endif
 
//
//  Define _CDECL as _cdecl only when using Symantec 68k products.
//
#if defined(__SC__) || defined(THINK_CPLUS) || defined(__MRC__)
    #define _CDECL          _cdecl
#else
    #define _CDECL
#endif
 
//
//  Define the Volatile and VOLATILE macros based on the compiler.
//
#define VOLATILE(x)     ((void) &x)
#if GENERATINGPOWERPC || defined(__SC__) || defined(THINK_CPLUS) || defined(__MWERKS__)
    #define Volatile        volatile
#else
    #define Volatile
#endif
 
 
#undef SystemSixOrLater
#define SystemSixOrLater    1
 
 
/*******************************************************************************
** Some Typedefs and constants
********************************************************************************/
 
#ifndef NULL
#define NULL        0
#endif
 
//
//  The following are parameter typedefs to force Symantec compilers to pass
//  two byte parameters as four byte parameters so you can call MPW built
//  shared libraries from Symantec built clients.
//
#if GENERATING68K
    typedef int             OSErrParm;
    typedef unsigned int    BooleanParm;
    typedef int             charParm;
    typedef unsigned int    ucharParm;
    typedef int             shortParm;
    typedef unsigned int    ushortParm;
    typedef long double     floatParm;
    typedef long double     doubleParm;
#else
    typedef OSErr           OSErrParm;
    typedef Boolean         BooleanParm;
    typedef char            charParm;
    typedef unsigned char   ucharParm;
    typedef short           shortParm;
    typedef unsigned short  ushortParm;
    typedef float           floatParm;
    typedef double          doubleParm;
#endif
 
/*******************************************************************************
** Some external routines
********************************************************************************/
 
#ifndef FIX_ASLM
#ifdef __cplusplus
extern "C" {
#endif
    char* strcpy(char* s1, const char* s2);
#ifdef __cplusplus
}
#endif
#endif
 
/*******************************************************************************
** Error Constants
********************************************************************************/
 
#define kNoError                        0
#define kASLMNotFoundErr                -3120
#define kASLMNoParentErr                -3121
#define kASLMParentNotFoundErr          -3122
#define kASLMNotRelatedErr              -3123
#define kASLMInvalidObjectErr           -3124
#define kASLMPoolCorruptedErr           -3125
#define kASLMOutOfMemoryErr             -3126
#define kASLMCodeNotLoadedErr           -3127
#define kASLMCouldNotLoadCodeErr        -3128
#define kASLMFilePreflightedErr         -3129
#define kASLMFileNotPreflightedErr      -3130
#define kASLMFileNotFoundErr            -3131
#define kASLMLibraryManagerNotLoadedErr -3132
#define kASLMDuplicateFoundErr          -3134
#define kASLMSeedChangedErr             -3135
#define kASLMUnconstructedObjectErr     -3136
#define kASLMInternalErr                -3137
#define kASLMVersionErr                 -3138
#define kASLMFolderNotFoundErr          -3139
#define kASLMFolderInUseErr             -3140
#define kASLMResourceNotFoundErr        -3141
#define kASLMInvalidSegmentNumberErr    -3142
#define kASLMNotAllowedNowErr           -3155
#define kASLMNotSupportedErr            -3167
 
/*******************************************************************************
** Typedefs
********************************************************************************/
 
//
//  ASLM uses CDECLProcPtr instead of ProcPtr in all of its interfaces. It is the
//  same as ProcPtr except when using SCpp. In this case it is declared as
//  _cdecl so it will have C calling conventions instead of Cpp.
//
typedef long (* _CDECL CDECLProcPtr)();
 
typedef void*           GlobalWorld;
#define kInvalidWorld   ((GlobalWorld)0)
 
typedef unsigned short  Version;
typedef unsigned long   VersionParm;    // for passing a version as a paramter
#define kAnyVersion     ((Version)0)
 
#define TFunctionSetID  TClassID
#define TLibraryID      TClassID
 
#define CastToFunctionSetID CastToClassID   /* for casting a cstring to a TFunctionSetID */
#define CastToLibraryID     CastToClassID   /* for casting a cstring to a TLibraryID */
 
#define FunctionSetID   CastToFunctionSetID /* for casting a cstring to a TFunctionSetID */
#define LibraryID       CastToLibraryID     /* for casting a cstring to a TLibraryID */
#ifndef ClassID     // make sure we don't conflict with MacApp
    #define ClassID     CastToClassID       /* for casting a cstring to a TLibraryID */
#endif
 
/*******************************************************************************
** Forward class declarations
********************************************************************************/
 
#ifdef __cplusplus
    class   TDynamic;
    class   TLibraryManager;
    class   TClassID;
    class   TFunctionSetID;
    class   TLibraryID;
    class   TLibrary;
    class   TFormattedStream;
    class   TMemoryPool;
    class   TStandardPool;
    class   TLibraryFile;
    class   TClassInfo;
    class   TException;
    class   TSimpleList;
    class   TFileSpec;
#else
    typedef char* TClassID;
    typedef void TDynamic;
    typedef void TLibraryManager;
    typedef void TFormattedStream;
    typedef void TStandardPool;
    typedef void TClassInfo;
    typedef void TLibrary;
    typedef void TMemoryPool;
#endif
 
 
/*******************************************************************************
** Memory definitions
********************************************************************************/
 
typedef int ZoneType;
 
#define kSystemZone             ((ZoneType)1)
#define kKernelZone             ((ZoneType)2)
#define kApplicZone             ((ZoneType)3)
#define kCurrentZone            ((ZoneType)4)
#define kTempZone               ((ZoneType)5)
 
typedef int MemoryType;
 
#define kNormalMemory           ((MemoryType)1)
#define kHoldMemory             ((MemoryType)2)
#define kLockMemory             ((MemoryType)3)
#define kLockMemoryContiguous   ((MemoryType)4)
 
/*******************************************************************************
** ASLM Gestalt selector
********************************************************************************/
 
#define gestaltASLMPPC 'slmp'
#define gestaltASLM68K 'aslm'
 
#if GENERATINGPOWERPC
    #define gestaltASLM gestaltASLMPPC
#else
    #define gestaltASLM gestaltASLM68K
#endif
 
/*
    If the ASLM gestalt selector returns NULL then ASLM did not load properly
    at boot time and is not available. Otherwise the version will be in the
    upper 2 bytes of the result and lower 2 bits of the result will contain
    information as described below.
*/
 
enum {
    gestaltASLMVersionMask  = 0xffff0000,   /*  Version is in upper 2 bytes of result */
    gestaltASLMPresentMask  = 0x0001,       /*  If first bit is set then ASLM was loaded
                                                at some point but may not be now. If you
                                                call InitLibraryManager, ASLM will load
                                                automatically, except at boot time, in
                                                which case it will set a flag so it stays
                                                loaded next time and then will reboot. */
    gestaltASLMLoadedMask   = 0x0002        /*  If second bit is set then ASLM is
                                                currently loaded. */
};
 
/*******************************************************************************
** Old interface definitions for backwards compatiblity.
********************************************************************************/
 
#ifndef SupportOldASLMInterfaces
#define SupportOldASLMInterfaces 1
#endif
 
#if SupportOldASLMInterfaces
    //
    // Old error code constants. New error code values are the same but the
    // names were changed by adding "ASLM" to the front and "err" to the end.
    //
    #define kNotFound                       -3120
    #define kNoParent                       -3121
    #define kParentNotFound                 -3122
    #define kNotRelated                     -3123
    #define kInvalidObject                  -3124
    #define kPoolCorrupted                  -3125
    #define kOutOfMemory                    -3126
    #define kCodeNotLoaded                  -3127
    #define kCouldNotLoadCode               -3128
    #define kFilePreflighted                -3129
    #define kFileNotPreflighted             -3130
    #define kFileNotFound                   -3131
    #define kLibraryManagerNotLoaded        -3132
    #define kDuplicateFound                 -3134
    #define kSeedChanged                    -3135
    #define kUnconstructedObject            -3136
    #define kInternalError                  -3137
    #define kVersionError                   -3138
    #define kFolderNotFound                 -3139
    #define kFolderInUse                    -3140
    #define kResourceNotFound               -3141
    #define kNotAllowedNow                  -3155
    #define kNotSupported                   -3167
 
    //
    //  The FSInfoGetParentID function was renamed to FSInfoGetInterfaceID
    //
    #define FSInfoGetParentID FSInfoGetInterfaceID
#endif
 
/*******************************************************************************
** STACKOBJECTONLY: Use in a class declaration so the object can only be created
** on the stack. This makes the constructors and destructors much smaller since
** they know they will never have to new or delete memory.
********************************************************************************/
 
#define STACKOBJECTONLY                                             \
    private:                                                        \
                void*   operator new(size_t) { return NULL; }       \
                void    operator delete(void*) {}
 
/*******************************************************************************
** Some "C" Global routines
**
** InitLibraryManager initializes a client to use the ASLM. All clients
** must make this call except for ASLM libraries. CleanupLibraryManager
** should be called when the client is done using the ASLM.
**
** GetLocalLibraryManager can be called after InitLibraryManager is called. If it
** returns NULL then InitLibraryManager failed.
********************************************************************************/
 
#ifdef __cplusplus
    extern "C" {
#endif
 
/*  -------------------------------------------------------------------------
    These functions are for use by applications or stand-alone code 
    resources only
    ------------------------------------------------------------------------- */
 
#ifdef __cplusplus
        
OSErr               InitLibraryManager(size_t poolsize = 0, ZoneType = kCurrentZone,
                                       MemoryType = kNormalMemory);
void                CleanupLibraryManager();
    
#else
 
OSErr               InitLibraryManager(size_t poolsize, int zoneType, int memType);
void                CleanupLibraryManager(void);
    
#endif
 
/*  -------------------------------------------------------------------------
    Call FragmentIsNonApplicationASLMClient before calling InitLibraryManager
    if you are writing a PowerPC CFM fragment that is not the main
    application code fragment.
    ------------------------------------------------------------------------- */
 
#if GENERATINGPOWERPC
    void FragmentIsNonApplicationASLMClient();
#endif
 
 
/*  -------------------------------------------------------------------------
    These functions can be used by any Shared Library Manager clients
    ------------------------------------------------------------------------- */
 
#ifdef __cplusplus
 
Boolean             IsDerivedFrom(const void*, const TClassID&);
const TClassID&     GetObjectsClassID(const void*);
const TClassID&     GetObjectsParentClassID(const void*);
unsigned short      GetObjectsVersion(const void*);
unsigned short      GetObjectsMinVersion(const void*);
size_t              GetObjectsSize(const void*);
TLibrary*           GetObjectsLocalLibrary(const void*);
TLibraryFile*       GetObjectsLocalLibraryFile(const void*);
TStandardPool*      GetObjectsLocalPool(const void*);
void                SetObjectsLocalPool(const void*, TStandardPool*);
 
void*               NewObject(const TClassID&, OSErr* = NULL,
                              TMemoryPool* = NULL);
void*               NewObjectWithParent(const TClassID&,
                                        const TClassID& parentID,
                                        OSErr* = NULL, TMemoryPool* = NULL);
void*               NewObjectFromStream(const TFormattedStream&,
                                        OSErr* = NULL, TMemoryPool* = NULL);
 
TClassInfo*         GetClassInfo(const TClassID&, OSErr* = NULL);
 
OSErr               VerifyClass(const TClassID&, const TClassID& parentID);
void*               CastObject(const void*, const TClassID& parentID, OSErr* = NULL);
void*               CastToMainObject(const void*);
 
OSErr               LoadClass(const TClassID&, BooleanParm forceAll);
OSErr               UnloadClass(const TClassID&);
Boolean             IsClassLoaded(const TClassID&);
 
OSErr               LoadFunctionSet(const TFunctionSetID&, BooleanParm forceAll);
OSErr               UnloadFunctionSet(const TFunctionSetID&);
Boolean             IsFunctionSetLoaded(const TFunctionSetID&);
 
CDECLProcPtr        GetFunctionPointer(const TFunctionSetID&, const char* funcName,
                                       OSErr* = NULL);
CDECLProcPtr        GetIndexedFunctionPointer(const TFunctionSetID&, unsigned int index,
                                              OSErr* = NULL);
 
OSErr               LoadLibraries(BooleanParm forceAll = true,
                                  BooleanParm doSelf = true);
OSErr               UnloadLibraries();
void                ResetFunctionSet(const TFunctionSetID* = NULL);
        
Boolean             TraceLogOn();
Boolean             TraceLogOff();
 
void                RegisterDynamicObject(TDynamic*);
void                UnregisterDynamicObject(TDynamic*);
    
TLibraryManager*    GetLocalLibraryManager();
    
TStandardPool*      GetLocalPool();
void                SetLocalPool(TStandardPool*);
TStandardPool*      GetClientPool();
TStandardPool*      GetDefaultPool();
void                SetDefaultPool(TStandardPool*);
TStandardPool*      GetSystemPool();
    
#else
    
void*               NewObject(const TClassID, OSErr*, TStandardPool*);
void*               NewObjectWithParent(const TClassID, const TClassID parentID,
                                        OSErr*, TMemoryPool*);
void*               NewObjectFromStream(const TFormattedStream*, OSErr*,
                                        TMemoryPool*);
 
TClassInfo*         GetClassInfo(const TClassID, OSErr*);
 
OSErr               VerifyClass(const TClassID, const TClassID parentID);
void*               CastObject(const void*, const TClassID parentID, OSErr*);
void*               CastToMainObject(const void*);
 
OSErr               LoadClass(const TClassID, BooleanParm forceAll);
OSErr               UnloadClass(const TClassID);
Boolean             IsClassLoaded(const TClassID);
 
OSErr               LoadFunctionSet(const TFunctionSetID, BooleanParm forceAll);
OSErr               UnloadFunctionSet(const TFunctionSetID);
Boolean             IsFunctionSetLoaded(const TFunctionSetID);
 
ProcPtr             GetFunctionPointer(const TFunctionSetID, const char* funcName,
                                       OSErr*);
ProcPtr             GetIndexedFunctionPointer(const TFunctionSetID, unsigned int index,
                                              OSErr*);
 
OSErr               LoadLibraries(BooleanParm forceAll, BooleanParm doSelf);
OSErr               UnloadLibraries(void);
void                ResetFunctionSet(const TFunctionSetID);
        
Boolean             TraceLogOn();
Boolean             TraceLogOff();
 
TLibraryManager*    GetLocalLibraryManager(void);
 
TStandardPool*      GetLocalPool();
void                SetLocalPool(TStandardPool*);
TStandardPool*      GetClientPool();
TStandardPool*      GetDefaultPool();
void                SetDefaultPool(TStandardPool*);
TStandardPool*      GetSystemPool();
 
#endif
 
/*
    These routines are declared in LibraryManagerUtilities.h, but are needed
    for the inlines below.
*/
 
void* SLMNewOperator(size_t, TMemoryPool*);
void SLMDeleteOperator(void*);
 
#ifdef __cplusplus
}
 
 
/*******************************************************************************
** CLASS TSimpleDynamic
**
** A base class for shared-library classes that has no virtual functions.  This
** class is NOT shared, since it is intended to be a trivial class that just
** forces the VTable to be at the front of the object.
********************************************************************************/
 
#if SINGLEOBJECT
class TSimpleDynamic : public SingleObject
#else
class TSimpleDynamic
#endif
{
    ASLM_COMPATIBLE
 
    public:
        virtual                 ~ _CDECL TSimpleDynamic();
        
                void*           operator new(size_t size, TMemoryPool* pool)    // from specified pool
                                    { return SLMNewOperator(size, pool); }
                void*           operator new(size_t size)                       // from default pool
                                    { return SLMNewOperator(size, 0); }
                void            operator delete(void* obj, size_t)
                                    { SLMDeleteOperator(obj); }
 
                const TClassID& GetObjectsClassID() const;
                const TClassID& GetObjectsParentClassID() const;
                unsigned short  GetObjectsVersion() const;
                unsigned short  GetObjectsMinVersion() const;
                size_t          GetObjectsSize() const;
                TLibrary*       GetObjectsLocalLibrary() const;
                TLibraryFile*   GetObjectsLocalLibraryFile() const;
                TStandardPool*  GetObjectsLocalPool() const;
                void            SetObjectsLocalPool(TStandardPool*) const;
    
                Boolean         IsDerivedFrom(const TClassID&) const;
                
    protected:
                                _CDECL TSimpleDynamic();
 
    private:
                                TSimpleDynamic(const TSimpleDynamic&);
                void            operator=(const TSimpleDynamic&);
};
 
/*******************************************************************************
** CLASS TDynamic
**
** The base class for shared-library classes with a set of common capabilities.
** This class provides the same capabilities as TStdDynamic.
********************************************************************************/
 
typedef int TraceControlType;
 
#define kTraceStatus    ((TraceControlType)1)
#define kTraceOn        ((TraceControlType)2)
#define kTraceOff       ((TraceControlType)3)
 
#define kTDynamicID "!$dyna,1.2"
 
#if SINGLEOBJECT
class TDynamic : public SingleObject
#else
class TDynamic
#endif
{
    ASLM_COMPATIBLE
 
    public:
        virtual                 ~ _CDECL TDynamic();
        
                void*           operator new(size_t size, TMemoryPool* pool)    // from specified pool
                                    { return SLMNewOperator(size, pool); }
                void*           operator new(size_t size)                       // from default pool
                                    { return SLMNewOperator(size, 0); }
                void            operator delete(void* obj, size_t)
                                    { SLMDeleteOperator(obj); }
                                    
 
        const TClassID&         GetObjectsClassID() const;
        const TClassID&         GetObjectsParentClassID() const;
                unsigned short  GetObjectsVersion() const;
                unsigned short  GetObjectsMinVersion() const;
                size_t          GetObjectsSize() const;
                TLibrary*       GetObjectsLocalLibrary() const;
                TLibraryFile*   GetObjectsLocalLibraryFile() const;
                TStandardPool*  GetObjectsLocalPool() const;
                void            SetObjectsLocalPool(TStandardPool*) const;
 
        virtual Boolean         _CDECL IsValid() const;
        
        virtual OSErr           _CDECL Inflate(TFormattedStream&);
        virtual OSErr           _CDECL Flatten(TFormattedStream&) const;
        virtual TDynamic*       _CDECL Clone(TStandardPool*) const;
        
        virtual char*           _CDECL GetVerboseName(char*) const;
        virtual void            _CDECL Dump() const;
        
                void            _CDECL Trace(char *formatStr, ...) const;
        virtual Boolean         _CDECL TraceControl(TraceControlType) const;
                Boolean         IsTraceOn() const;  
                Boolean         TraceOn() const;
                Boolean         TraceOff() const;
    
                Boolean         IsDerivedFrom(const TClassID&) const;
                
    protected:
                                _CDECL TDynamic();
 
    private:
                                TDynamic(const TDynamic&);
                void            operator=(const TDynamic&);
};
 
/*  -------------------------------------------------------------------------
    Inline methods for TDynamic
    ------------------------------------------------------------------------- */
 
    inline Boolean TDynamic::IsTraceOn() const
    {
        return TraceControl(kTraceStatus);
    }
 
    inline Boolean TDynamic::TraceOn() const
    {
        return TraceControl(kTraceOn);
    }
 
    inline Boolean TDynamic::TraceOff() const
    {
        return TraceControl(kTraceOff);
    }
 
/*******************************************************************************
** CLASS MDynamic
**
** A base class for shared-library classes, which has one 1 virtual function (the
** destructor).  This class is NOT shared, since it is intended to be a trivial class
** that can be used to force the VTable to be at the front of the object for
** mixin classes.
********************************************************************************/
 
class MDynamic
{
    ASLM_COMPATIBLE
 
    public:
        virtual                 ~_CDECL MDynamic();
        
    protected:
                                _CDECL MDynamic();
 
    private:
                                MDynamic(const MDynamic&);
                void            operator=(const MDynamic&);
};
 
/*******************************************************************************
** CLASS TStdDynamic
**
** The base class for shared-library classes with a set of common capabilities.
** This class provides the same capabilities as TDynamic below, but is for
** classes that you don't want to descend from SingleObject.
********************************************************************************/
 
#define kTStdDynamicID "!$sdyn,1.2"
 
class TStdDynamic
{
    ASLM_COMPATIBLE
 
    public:
        virtual                 ~ _CDECL TStdDynamic();
        
                void*           operator new(size_t size, TMemoryPool* pool)    // from specified pool
                                    { return SLMNewOperator(size, pool); }
                void*           operator new(size_t size)                       // from default pool
                                    { return SLMNewOperator(size, 0); }
                void            operator delete(void* obj, size_t)
                                    { SLMDeleteOperator(obj); }
                                    
 
        const TClassID&         GetObjectsClassID() const;
                unsigned short  GetObjectsVersion() const;
                unsigned short  GetObjectsMinVersion() const;
                size_t          GetObjectsSize() const;
                TLibrary*       GetObjectsLocalLibrary() const;
                TLibraryFile*   GetObjectsLocalLibraryFile() const;
                TStandardPool*  GetObjectsLocalPool() const;
                void            SetObjectsLocalPool(TStandardPool*) const;
 
        virtual Boolean         _CDECL IsValid() const;
        
        virtual OSErr           _CDECL Inflate(TFormattedStream&);
        virtual OSErr           _CDECL Flatten(TFormattedStream&) const;
        virtual TDynamic*       _CDECL Clone(TStandardPool*) const;
        
        virtual char*           _CDECL GetVerboseName(char*) const;
        virtual void            _CDECL Dump() const;
        
                void            _CDECL Trace(char *formatStr, ...) const;
        virtual Boolean         _CDECL TraceControl(TraceControlType) const;
                Boolean         IsTraceOn() const;  
                Boolean         TraceOn() const;
                Boolean         TraceOff() const;
    
                Boolean         IsDerivedFrom(const TClassID&) const;
                
    protected:
                                _CDECL TStdDynamic();
 
    private:
                                TStdDynamic(const TDynamic&);
                void            operator=(const TDynamic&);
};
 
/*  -------------------------------------------------------------------------
    Inline methods for TStdDynamic
    ------------------------------------------------------------------------- */
    
    inline Boolean TStdDynamic::IsTraceOn() const
    {
        return TraceControl(kTraceStatus);
    }
 
    inline Boolean TStdDynamic::TraceOn() const
    {
        return TraceControl(kTraceOn);
    }
 
    inline Boolean TStdDynamic::TraceOff() const
    {
        return TraceControl(kTraceOff);
    }
 
/*******************************************************************************
** CLASS TStdSimpleDynamic
**
** A base class for shared-library classes that has no virtual functions.  This
** class is NOT shared, since it is intended to be a trivial class that just
** forces the VTable to be at the front of the object.
********************************************************************************/
 
class TStdSimpleDynamic
{
    ASLM_COMPATIBLE
 
    public:
        virtual                 ~ _CDECL TStdSimpleDynamic();
        
                void*           operator new(size_t size, TMemoryPool* pool)    // from specified pool
                                    { return SLMNewOperator(size, pool); }
                void*           operator new(size_t size)                       // from default pool
                                    { return SLMNewOperator(size, 0); }
                void            operator delete(void* obj, size_t)
                                    { SLMDeleteOperator(obj); }
 
                const TClassID& GetObjectsClassID() const;
                unsigned short  GetObjectsVersion() const;
                unsigned short  GetObjectsMinVersion() const;
                size_t          GetObjectsSize() const;
                TLibrary*       GetObjectsLocalLibrary() const;
                TLibraryFile*   GetObjectsLocalLibraryFile() const;
                TStandardPool*  GetObjectsLocalPool() const;
                void            SetObjectsLocalPool(TStandardPool*) const;
    
                Boolean         IsDerivedFrom(const TClassID&) const;
                
    protected:
                                _CDECL TStdSimpleDynamic();
 
    private:
                                TStdSimpleDynamic(const TStdSimpleDynamic&);
                void            operator=(const TStdSimpleDynamic&);
};
 
#if defined(__SC__) || defined(__MRC__)
 
/*******************************************************************************
** CLASS TSCSimpleDynamic
**
** A base class for shared-library classes that has no virtual functions.  This
** class is NOT shared, since it is intended to be a trivial class that just
** forces the VTable to be at the front of the object, and override new to
** use the ASLM operators. It is used as a simple base class for Symantec C++ objects.
** This is the normal subclass for Symantec C++ objects that are not going to 
** intermix with MPW C++ objects.
********************************************************************************/
 
class TSCSimpleDynamic
{
    ASLM_COMPATIBLE
 
    public:
        virtual                 ~TSCSimpleDynamic();
        
                void*           operator new(size_t size, TMemoryPool* pool)    // from specified pool
                                    { return SLMNewOperator(size, pool); }
                void*           operator new(size_t size)                       // from default pool
                                    { return SLMNewOperator(size, 0); }
                void            operator delete(void* obj, size_t)
                                    { SLMDeleteOperator(obj); }
 
                const TClassID& GetObjectsClassID() const;
                const TClassID& GetObjectsParentClassID() const;
                unsigned short  GetObjectsVersion() const;
                unsigned short  GetObjectsMinVersion() const;
                size_t          GetObjectsSize() const;
                TLibrary*       GetObjectsLocalLibrary() const;
                TLibraryFile*   GetObjectsLocalLibraryFile() const;
                TStandardPool*  GetObjectsLocalPool() const;
                void            SetObjectsLocalPool(TStandardPool*) const;
    
                Boolean         IsDerivedFrom(const TClassID&) const;
                
    protected:
                                TSCSimpleDynamic();
 
    private:
                                TSCSimpleDynamic(const TSCSimpleDynamic&);
                void            operator=(const TSCSimpleDynamic&);
};
 
/*******************************************************************************
** CLASS TSCDynamic
**
** The base class for shared-library classes with a set of common capabilities.
** This class provides the same capabilities as TStdDynamic.  It is only for
** Symantec C++ implementations
********************************************************************************/
 
#define kTSCDynamicID "!$scdy,1.2"
 
class TSCDynamic
{
    ASLM_COMPATIBLE
 
    public:
        virtual                 ~ _cdecl TSCDynamic();
        
                void*           operator new(size_t size, TMemoryPool* pool)    // from specified pool
                                    { return SLMNewOperator(size, pool); }
                void*           operator new(size_t size)                       // from default pool
                                    { return SLMNewOperator(size, 0); }
                void            operator delete(void* obj, size_t)
                                    { SLMDeleteOperator(obj); }
 
        const TClassID&         GetObjectsClassID() const;
        const TClassID&         GetObjectsParentClassID() const;
                unsigned short  GetObjectsVersion() const;
                unsigned short  GetObjectsMinVersion() const;
                size_t          GetObjectsSize() const;
                TLibrary*       GetObjectsLocalLibrary() const;
                TLibraryFile*   GetObjectsLocalLibraryFile() const;
                TStandardPool*  GetObjectsLocalPool() const;
                void            SetObjectsLocalPool(TStandardPool*) const;
 
        virtual Boolean         _cdecl IsValid() const;
        
        virtual OSErr           _cdecl Inflate(TFormattedStream&);
        virtual OSErr           _cdecl Flatten(TFormattedStream&) const;
        virtual TSCDynamic*     _cdecl Clone(TStandardPool*) const;
        
        virtual char*           _cdecl GetVerboseName(char*) const;
        virtual void            _cdecl Dump() const;
        
                void            _cdecl Trace(char *formatStr, ...) const;
        virtual Boolean         _cdecl TraceControl(TraceControlType) const;
                Boolean         IsTraceOn() const;  
                Boolean         TraceOn() const;
                Boolean         TraceOff() const;
    
                Boolean         IsDerivedFrom(const TClassID&) const;
                
    protected:
                                _cdecl TSCDynamic();
 
    private:
                                TSCDynamic(const TSCDynamic&);
                void            operator=(const TSCDynamic&);
};
 
/*  -------------------------------------------------------------------------
    Inline methods for TSCDynamic
    ------------------------------------------------------------------------- */
 
    inline Boolean TSCDynamic::IsTraceOn() const
    {
        return TraceControl(kTraceStatus);
    }
 
    inline Boolean TSCDynamic::TraceOn() const
    {
        return TraceControl(kTraceOn);
    }
 
    inline Boolean TSCDynamic::TraceOff() const
    {
        return TraceControl(kTraceOff);
    }
    
#endif  /* __SC__ */
#endif  /* __cplusplus */
 
/*******************************************************************************
** Class TClassID, TFunctionSetID, and TLibraryID
**
** TFunctionSetID and TLibraryID are typedef'd to be the same as TClassID
********************************************************************************/
 
#define kMaxClassIDSize     255
 
#ifdef __cplusplus
 
const TClassID& CastToClassID(const char* str); // cast a char* to a TClassID
 
Boolean operator==(const TClassID&, const char *);
Boolean operator!=(const TClassID&, const char *);
Boolean operator==(const char *, const TClassID&);
Boolean operator!=(const char *, const TClassID&);
 
class TClassID
{
    public:
        void*       operator new(size_t, size_t strLen, TMemoryPool* thePool = NULL)
                    {
                        return SLMNewOperator(strLen+1, thePool);
                    }
 
        void*       operator new(size_t)
                    {
                        return SLMNewOperator(kMaxClassIDSize+1, NULL);
                    }
                        
        void        operator delete(void* obj, size_t)
                        { SLMDeleteOperator(obj); }
 
                    TClassID();
                    TClassID(const TClassID&);
 
                    operator const char*() const;       // cast to a const char *
 
        Version     _CDECL ExtractVersion() const;
        size_t      _CDECL GetLength() const;
        
        TClassID&   operator=(const TClassID&);
 
        Boolean     _CDECL operator==(const TClassID&) const;
        Boolean     operator!=(const TClassID&) const;
 
    private:
        char                fClassIDStr[kMaxClassIDSize + 1];
};
 
/*  -------------------------------------------------------------------------
    Inline methods for TClassID
    ------------------------------------------------------------------------- */
 
    //
    // constructors
    //
 
    inline TClassID::TClassID()
    {
        fClassIDStr[0] = 0;
    }
    
    inline TClassID::TClassID(const TClassID& classID)
    {
        strcpy(fClassIDStr, classID.fClassIDStr);
    }
 
    //
    // cast operators
    //
 
    inline const TClassID& CastToClassID(const char* str)
    {
        return *(const TClassID*)str;
    }
    
    inline TClassID::operator const char *() const
    {
        return fClassIDStr;
    }
 
    //
    // compare operators
    //
    
    inline Boolean TClassID::operator!=(const TClassID& classID) const
    {
        return !(*this == classID);
    }
    
    inline Boolean operator!=(const TClassID& id1, const char *id2)
    {
        return !(id1 == CastToClassID(id2));
    }
 
    inline Boolean operator!=(const char *id1, const TClassID& id2)
    {
        return !(id2 == CastToClassID(id1));
    }
    
    inline Boolean operator==(const TClassID& id1, const char *id2)
    {
        return (id1 == CastToClassID(id2));
    }
    
    inline Boolean operator==(const char *id1, const TClassID& id2)
    {
        return (id2 == CastToClassID(id1));
    }
 
    //
    // assignment operators
    //
    
    inline TClassID& TClassID::operator=(const TClassID& classID)
    {
        strcpy(fClassIDStr, classID.fClassIDStr);
        return *this;
    }
    
#endif
 
/*******************************************************************************
** Class TLibraryManager
**
** The user's interface to the world! 
********************************************************************************/
 
#ifdef __cplusplus
 
#define kTLibraryManagerID "!$lmgr,1.2"
 
class TLibraryManager : public TDynamic 
{
 
    private:
        virtual                 ~ _CDECL TLibraryManager();
                                _CDECL TLibraryManager(TStandardPool* = NULL, TLibraryFile* = NULL);
 
    public:
        virtual void            _CDECL Dump() const;
 
        // New Methods
        
        virtual void*           _CDECL NewObject(const TClassID& classID,
                                    OSErr* = NULL, TMemoryPool* = NULL) const;
        virtual void*           _CDECL NewObject(const TClassID& classID, const TClassID& baseClassID,
                                    OSErr* = NULL, TMemoryPool* = NULL) const;
        virtual void*           _CDECL NewObject(const TFormattedStream&,
                                    OSErr* = NULL, TMemoryPool* = NULL) const;
 
        virtual TClassInfo*     _CDECL GetClassInfo(const TClassID&, OSErr* = NULL) const;
 
        virtual OSErr           _CDECL VerifyClass(const TClassID& classID, const TClassID& baseClassID) const;
        virtual void*           _CDECL CastObject(const void* obj, const TClassID& parentID,
                                                OSErr* = NULL) const;
        virtual void*           _CDECL CastToMainObject(const void* obj) const;
        
        virtual OSErr           _CDECL LoadClass(const TClassID&, BooleanParm loadAll = false);
        virtual OSErr           _CDECL UnloadClass(const TClassID&);
        virtual Boolean         _CDECL IsClassLoaded(const TClassID&) const;
 
                OSErr           LoadFunctionSet(const TFunctionSetID&, BooleanParm loadAll = false);
                OSErr           UnloadFunctionSet(const TFunctionSetID&);
                Boolean         IsFunctionSetLoaded(const TFunctionSetID&) const;
        
        virtual CDECLProcPtr    _CDECL GetFunctionPointer(const TFunctionSetID&,
                                                   const char* funcName,
                                                   OSErr* = NULL);
        virtual CDECLProcPtr    _CDECL GetFunctionPointer(const TFunctionSetID&,
                                                   unsigned int index,
                                                   OSErr* = NULL);
        
        virtual OSErr           _CDECL LoadLibraries(BooleanParm forceAll = true,
                                                   BooleanParm doSelf = true);
        virtual OSErr           _CDECL UnloadLibraries();
        virtual void            _CDECL ResetFunctionSet(const TFunctionSetID* = NULL);
        
        virtual Boolean         _CDECL TraceLogOn();
        virtual Boolean         _CDECL TraceLogOff();
        
        virtual void            _CDECL RegisterDynamicObject(TDynamic*);
        virtual void            _CDECL UnregisterDynamicObject(TDynamic*);
 
                void            SetObjectPool(TStandardPool*);
                TStandardPool*  GetObjectPool() const;
                void            SetDefaultPool(TStandardPool*);
                TStandardPool*  GetDefaultPool() const;
                GlobalWorld     _CDECL GetGlobalWorld() const;
        virtual TLibrary*       _CDECL GetLibrary() const;
        virtual TLibraryFile*   _CDECL GetLibraryFile() const;
 
    private:
                                TLibraryManager(const TLibraryManager&);
                void            operator=(const TLibraryManager&);
    private:        
        TStandardPool*          fPool;          // pool used for new objects and local pool
        TLibraryFile*           fLibraryFile;
        TStandardPool*          fDefaultPool;
        GlobalWorld             fGlobalWorld;
 
};
 
/*  -------------------------------------------------------------------------
    Inline Methods for TLibraryManager
    ------------------------------------------------------------------------- */
    
    inline OSErr TLibraryManager::LoadFunctionSet(const TFunctionSetID& functionSetID, BooleanParm loadAll)
    {
        return LoadClass(functionSetID, loadAll);
    }
    
    inline OSErr TLibraryManager::UnloadFunctionSet(const TFunctionSetID& functionSetID)
    {
        return UnloadClass(functionSetID);
    }
    
    inline Boolean TLibraryManager::IsFunctionSetLoaded(const TFunctionSetID& functionSetID) const
    {
        return IsClassLoaded(functionSetID);
    }
    
    inline TStandardPool* TLibraryManager::GetObjectPool() const
    {
        return fPool;
    }
    
    inline void TLibraryManager::SetObjectPool(TStandardPool* thePool)
    {
        fPool = thePool;
    }
        
    inline TStandardPool* TLibraryManager::GetDefaultPool() const
    {
        return fDefaultPool;
    }
 
    inline void TLibraryManager::SetDefaultPool(TStandardPool* thePool)
    {
        fDefaultPool = thePool;
    }
    
    inline GlobalWorld TLibraryManager::GetGlobalWorld() const
    {
        return fGlobalWorld;
    }
 
/*  -------------------------------------------------------------------------
    Inline for IsDerivedFrom
    ------------------------------------------------------------------------- */
 
    inline Boolean IsDerivedFrom(const void* obj, const TClassID& id)
    {
        return (GetLocalLibraryManager()->CastObject(obj, id) != NULL);
    }
 
/*  -------------------------------------------------------------------------
    Inline methods for TDynamic
    ------------------------------------------------------------------------- */
 
    inline Boolean TDynamic::IsDerivedFrom(const TClassID& id) const
    {
        return ::IsDerivedFrom(this, id);
    }
 
    inline const TClassID& TDynamic::GetObjectsClassID() const
    {
        return ::GetObjectsClassID(this);
    }
 
    inline const TClassID& TDynamic::GetObjectsParentClassID() const
    {
        return ::GetObjectsParentClassID(this);
    }
 
    inline unsigned short TDynamic::GetObjectsVersion() const
    {
        return ::GetObjectsVersion(this);
    }
 
    inline unsigned short TDynamic::GetObjectsMinVersion() const
    {
        return ::GetObjectsMinVersion(this);
    }
 
    inline size_t TDynamic::GetObjectsSize() const
    {
        return ::GetObjectsSize(this);
    }
 
    inline TLibrary* TDynamic::GetObjectsLocalLibrary() const
    {
        return ::GetObjectsLocalLibrary(this);
    }
 
    inline TLibraryFile* TDynamic::GetObjectsLocalLibraryFile() const
    {
        return ::GetObjectsLocalLibraryFile(this);
    }
 
    inline TStandardPool* TDynamic::GetObjectsLocalPool() const
    {
        return ::GetObjectsLocalPool(this);
    }
 
    inline void TDynamic::SetObjectsLocalPool(TStandardPool* pool) const
    {
        ::SetObjectsLocalPool(this, pool);
    }
    
/*  -------------------------------------------------------------------------
    Inline methods for TSimpleDynamic
    ------------------------------------------------------------------------- */
 
    inline const TClassID& TSimpleDynamic::GetObjectsClassID() const
    {
        return ((const TDynamic*)this)->GetObjectsClassID();
    }
 
    inline const TClassID& TSimpleDynamic::GetObjectsParentClassID() const
    {
        return ((const TDynamic*)this)->GetObjectsParentClassID();
    }
 
    inline unsigned short TSimpleDynamic::GetObjectsVersion() const
    {
        return ::GetObjectsVersion(this);
    }
 
    inline unsigned short TSimpleDynamic::GetObjectsMinVersion() const
    {
        return ::GetObjectsMinVersion(this);
    }
 
    inline size_t TSimpleDynamic::GetObjectsSize() const
    {
        return ((const TDynamic*)this)->GetObjectsSize();
    }
 
    inline TLibrary* TSimpleDynamic::GetObjectsLocalLibrary() const
    {
        return ((const TDynamic*)this)->GetObjectsLocalLibrary();
    }
 
    inline TLibraryFile* TSimpleDynamic::GetObjectsLocalLibraryFile() const
    {
        return ((const TDynamic*)this)->GetObjectsLocalLibraryFile();
    }
 
    inline TStandardPool* TSimpleDynamic::GetObjectsLocalPool() const
    {
        return ((const TDynamic*)this)->GetObjectsLocalPool();
    }
 
    inline void TSimpleDynamic::SetObjectsLocalPool(TStandardPool* pool) const
    {
        ((const TDynamic*)this)->SetObjectsLocalPool(pool);
    }
 
    inline Boolean TSimpleDynamic::IsDerivedFrom(const TClassID& id) const
    {
        return ((const TDynamic*)this)->IsDerivedFrom(id);
    }
    
/*  -------------------------------------------------------------------------
    Inline methods for TStdDynamic
    ------------------------------------------------------------------------- */
 
    inline const TClassID& TStdDynamic::GetObjectsClassID() const
    {
        return ((const TDynamic*)this)->GetObjectsClassID();
    }
 
    inline unsigned short TStdDynamic::GetObjectsVersion() const
    {
        return ::GetObjectsVersion(this);
    }
 
    inline unsigned short TStdDynamic::GetObjectsMinVersion() const
    {
        return ::GetObjectsMinVersion(this);
    }
 
    inline size_t TStdDynamic::GetObjectsSize() const
    {
        return ((const TDynamic*)this)->GetObjectsSize();
    }
 
    inline TLibrary* TStdDynamic::GetObjectsLocalLibrary() const
    {
        return ((const TDynamic*)this)->GetObjectsLocalLibrary();
    }
 
    inline TLibraryFile* TStdDynamic::GetObjectsLocalLibraryFile() const
    {
        return ((const TDynamic*)this)->GetObjectsLocalLibraryFile();
    }
 
    inline TStandardPool* TStdDynamic::GetObjectsLocalPool() const
    {
        return ((const TDynamic*)this)->GetObjectsLocalPool();
    }
 
    inline void TStdDynamic::SetObjectsLocalPool(TStandardPool* pool) const
    {
        ((const TDynamic*)this)->SetObjectsLocalPool(pool);
    }
    
    inline Boolean TStdDynamic::IsDerivedFrom(const TClassID& id) const
    {
        return ((const TDynamic*)this)->IsDerivedFrom(id);
    }
 
/*  -------------------------------------------------------------------------
    Inline methods for TStdSimpleDynamic
    ------------------------------------------------------------------------- */
 
    inline const TClassID& TStdSimpleDynamic::GetObjectsClassID() const
    {
        return ((const TDynamic*)this)->GetObjectsClassID();
    }
 
    inline unsigned short TStdSimpleDynamic::GetObjectsVersion() const
    {
        return ::GetObjectsVersion(this);
    }
 
    inline unsigned short TStdSimpleDynamic::GetObjectsMinVersion() const
    {
        return ::GetObjectsMinVersion(this);
    }
 
    inline size_t TStdSimpleDynamic::GetObjectsSize() const
    {
        return ((const TDynamic*)this)->GetObjectsSize();
    }
 
    inline TLibrary* TStdSimpleDynamic::GetObjectsLocalLibrary() const
    {
        return ((const TDynamic*)this)->GetObjectsLocalLibrary();
    }
 
    inline TLibraryFile* TStdSimpleDynamic::GetObjectsLocalLibraryFile() const
    {
        return ((const TDynamic*)this)->GetObjectsLocalLibraryFile();
    }
 
    inline TStandardPool* TStdSimpleDynamic::GetObjectsLocalPool() const
    {
        return ((const TDynamic*)this)->GetObjectsLocalPool();
    }
 
    inline void TStdSimpleDynamic::SetObjectsLocalPool(TStandardPool* pool) const
    {
        ((const TDynamic*)this)->SetObjectsLocalPool(pool);
    }
    
    inline Boolean TStdSimpleDynamic::IsDerivedFrom(const TClassID& id) const
    {
        return ((const TDynamic*)this)->IsDerivedFrom(id);
    }
    
#if defined(__SC__) || defined(__MRC__)
 
/*  -------------------------------------------------------------------------
    Inline methods for TSCDynamic
    ------------------------------------------------------------------------- */
 
    inline Boolean TSCDynamic::IsDerivedFrom(const TClassID& id) const
    {
        return ::IsDerivedFrom(this, id);
    }
 
    inline const TClassID& TSCDynamic::GetObjectsClassID() const
    {
        return ::GetObjectsClassID(this);
    }
 
    inline const TClassID& TSCDynamic::GetObjectsParentClassID() const
    {
        return ::GetObjectsParentClassID(this);
    }
 
    inline unsigned short TSCDynamic::GetObjectsVersion() const
    {
        return ::GetObjectsVersion(this);
    }
 
    inline unsigned short TSCDynamic::GetObjectsMinVersion() const
    {
        return ::GetObjectsMinVersion(this);
    }
 
    inline size_t TSCDynamic::GetObjectsSize() const
    {
        return ::GetObjectsSize(this);
    }
 
    inline TLibrary* TSCDynamic::GetObjectsLocalLibrary() const
    {
        return ::GetObjectsLocalLibrary(this);
    }
 
    inline TLibraryFile* TSCDynamic::GetObjectsLocalLibraryFile() const
    {
        return ::GetObjectsLocalLibraryFile(this);
    }
 
    inline TStandardPool* TSCDynamic::GetObjectsLocalPool() const
    {
        return ::GetObjectsLocalPool(this);
    }
 
    inline void TSCDynamic::SetObjectsLocalPool(TStandardPool* pool) const
    {
        ::SetObjectsLocalPool(this, pool);
    }
    
/*  -------------------------------------------------------------------------
    Inline methods for TSCSimpleDynamic
    ------------------------------------------------------------------------- */
 
    inline const TClassID& TSCSimpleDynamic::GetObjectsClassID() const
    {
        return ((const TSCDynamic*)this)->GetObjectsClassID();
    }
 
    inline const TClassID& TSCSimpleDynamic::GetObjectsParentClassID() const
    {
        return ((const TSCDynamic*)this)->GetObjectsParentClassID();
    }
 
    inline unsigned short TSCSimpleDynamic::GetObjectsVersion() const
    {
        return ::GetObjectsVersion(this);
    }
 
    inline unsigned short TSCSimpleDynamic::GetObjectsMinVersion() const
    {
        return ::GetObjectsMinVersion(this);
    }
 
    inline size_t TSCSimpleDynamic::GetObjectsSize() const
    {
        return ((const TSCDynamic*)this)->GetObjectsSize();
    }
 
    inline TLibrary* TSCSimpleDynamic::GetObjectsLocalLibrary() const
    {
        return ((const TSCDynamic*)this)->GetObjectsLocalLibrary();
    }
 
    inline TLibraryFile* TSCSimpleDynamic::GetObjectsLocalLibraryFile() const
    {
        return ((const TSCDynamic*)this)->GetObjectsLocalLibraryFile();
    }
 
    inline TStandardPool* TSCSimpleDynamic::GetObjectsLocalPool() const
    {
        return ((const TSCSimpleDynamic*)this)->GetObjectsLocalPool();
    }
 
    inline void TSCSimpleDynamic::SetObjectsLocalPool(TStandardPool* pool) const
    {
        ((const TSCSimpleDynamic*)this)->SetObjectsLocalPool(pool);
    }
 
    inline Boolean TSCSimpleDynamic::IsDerivedFrom(const TClassID& id) const
    {
        return ((const TSCSimpleDynamic*)this)->IsDerivedFrom(id);
    }
    
#endif      /* __SC__ */
#endif      /* __cplusplus */
 
/*******************************************************************************
** EXCEPTION Handling
**
** Some RULES:
** 1) Never propogate a failure outside of a constructor or destructor.
**    If your constructor or destructor can call something which fails, it
**    _must_ CATCH the failure and not re-propogate it.
** 2) Never create an object inside of a "try" block which you cannot 
**    destroy (especially an auto object).
** 3) if you are going to just RERAISE the exception, or Fail 
**    with a different error, you must manually call the destructors 
**    of any  auto objects that are still in scope!
** 4) Any variables that are changed inside the "try", and which are tested
**    inside a CATCH, CATCH_ALL, or FINALLY must be declared "VOLATILE" 
**    (Use the VOLATILE macro above until C++ and volatile work!)
** 5) Never call Fail while an auto variable is in scope - it's 
**    destructor will not be called unless you call it manually.
** 6) FINALLY is always entered after TRY unless a CATCH clause raises
**    (or re-raises) an exception (this is true even if an exception was
**    not thrown).
********************************************************************************/
 
typedef struct TException   TException;
 
struct TException
{
    TException*         fPrev;
    size_t              fReserved;
#if GENERATINGPOWERPC
    long                fBuffer[33];
#endif
#if GENERATING68K
    long                fBuffer[12];
#endif
    char*               fMessage;
    void*               fPtr;
    OSErr               fError;
};
 
#ifdef __cplusplus
extern "C" {
#endif
 
void        PushException(TException*);
TException* PopException(TException*);
Boolean     MatchException(TException*, long);
 
#if GENERATING68K
    #pragma parameter __D0 SetupException(__A0)
    int SetupException(long* val) =
    {
        0x43fa, 0x0008, /* lea      *+10,a1 */
        0x48d0, 0xdefc, /* movem.l  d2-d7/a1-a4/a6/a7,(a0) */
        0x7000          /* moveq    #0,d0 */
    };
#else
    int SetupException(long* val);
#endif
 
#ifdef __cplusplus
}
#endif
    
/*  -----------------------------------------------------------------
    Some important functions for exception handling
    ----------------------------------------------------------------- */
 
#ifdef __cplusplus
extern "C" {
    void Fail(long err, const char* msg=NULL);
}
#else
    void Fail(long err, const char* msg);
#endif
 
#ifdef __cplusplus
    inline void FailNULL(void* val, long err, const char* msg=NULL) 
    { 
        if (val == 0) 
            Fail(err, msg); 
    }
#else
    #define FailNULL(val, err, msg)     \
        if (val == 0) { Fail(err, msg); } else {}
#endif
 
#if qDebug
    #define DebugFail(err, msg)             Fail(err, msg)
    #define DebugFailNULL(ptr, err, msg)    FailNULL(ptr, err, msg)
#else
    #define DebugFail(err, msg)             Fail(err, NULL)
    #define DebugFailNULL(ptr, err, msg)    FailNULL(ptr, err, NULL)
#endif
 
 
#define ErrorCode()                 (except.fError)
#define ErrorMessage()              (except.fMessage)
 
/*  -----------------------------------------------------------------
    The RAISE/RERAISE/TRY/CATCH/CATCH_ALL/FINALLY/ENDTRY macros
    ----------------------------------------------------------------- */
 
#define RAISE(x)    Fail(x,NULL)
        
#define RERAISE     Fail(ErrorCode(), ErrorMessage())
 
#define TRY                                                 \
    {                                                       \
        Boolean     finallyUsed = false;                    \
        TException  except;                                 \
        VOLATILE(finallyUsed);                              \
        VOLATILE(except);                                   \
        PushException(&except);                             \
        if (SetupException(except.fBuffer) == 0)            \
        {
        
#define CATCH(e)                                            \
        }                                                   \
        else if (MatchException(&except, e))                \
        { 
        
        
#define CATCH_ALL                                           \
        }                                                   \
        else                                                \
        { 
        
        
#define FINALLY                                             \
        }                                                   \
        PopException(&except);                              \
        finallyUsed = true;                                 \
        {
        
#define ENDTRY                                              \
        }                                                   \
        PopException(&except);                              \
        if (finallyUsed)                                    \
            if (ErrorCode() != kNoError) RERAISE;           \
    }
 
#endif