Exceptions.h

/*------------------------------------------------------------------------------------------
 
    Program:    CPlusTESample 2.0
    File:       Exceptions.h
 
    by Andrew Shebanow (original version by Andy Heninger)
    of Apple Macintosh Developer Technical Support
 
    Copyright © 1989-1990 Apple Computer, Inc.
    All rights reserved.
 
    This header defines a way for C++ code to do MacApp style Failure
    handling in a convenient way. In Object Pascal, Failure handlers
    are typically nested procedures which can reference local variables
    and such. In C++, there isn't any such thing as nested procedures,
    so we have to resort to hackery and define some lovely preprocessor
    macros.
 
    You use these macros inside a typical method like this:
 
        TRY
        {
            // stuff which might fail
        }
        RECOVER
        {
            // recovery stuff
        }
        ENDTRY
 
    Because all of the error handling is done inside of the function which
    caused the error, you can access local variables and such just like
    those Pascal guys do.
 
    How does it work? Well, it all depends on the C standard library
    setjmp/longjmp routines, which are explained in depth in the MPW
    C Reference. Basically, what they are is a mechanism for doing a
    non-local goto by saving and restoring the registers and the PC.
 
    How do you recover from an error? Basically, you just do a goto:
 
            TRY
            {
                // stuff which might fail
            }
            RECOVER
            {
                // recovery stuff
                goto recoveredSuccessfully;
            }
            ENDTRY
        recoveredSuccessfully:
            // do some more fun stuff
 
    This will drop you out of the failure mechanism entirely.
 
    For more examples, see the code in TApplication & TDocument.
 
------------------------------------------------------------------------------------------*/
 
#ifndef __EXCEPTIONS__
#define __EXCEPTIONS__
 
#ifndef __TYPES__
#include <Types.h>
#endif
 
#ifndef __SETJMP__
#include <SetJmp.h>
#endif
 
#include "UMAFailure.h"
 
extern "C" {
    // Since we eat the error code and message that the MacApp failure unit
    // passes us, we need to store them someplace where your failure
    // handling code can get at it. We use global variables (keen, eh?).
    extern long gFailMessage;       // Current failure message
    extern short gFailError;        // Current failure error
 
    pascal void StandardHandler(short e, long m, void* Handler_StaticLink);
};
 
#define TRY \
    { \
        jmp_buf errorBuf; \
        if (! setjmp(errorBuf) ) { \
            FailInfo    fi; \
            CatchFailures(&fi, StandardHandler, errorBuf);
 
#define RECOVER \
            Success(&fi); \
            } \
        else \
            {
 
/*
    The default MacApp/Object Pascal semantics are that returning from
    an error handler will go to the next failure handler on the
    stack.  The way we do this in C++ is that we call failure
    again with the same error information.  We can use a goto out
    of the RECOVER..ENDTRY block to stop the error processing.
 */
 
#define ENDTRY \
            Failure(gFailError, gFailMessage); \
            } \
    }
 
#endif