home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------------------
-
- 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
-