ftp.nice.ch/Attic/openStep/implementation/gnustep/sources/libFoundation.0.7.tgz#/libFoundation-0.7/libFoundation/doc/exceptions.txt

This is exceptions.txt in view mode; [Download] [Up]

Exceptions
    The exception handling mechanism provides several powerful features
    found in languages like C++ or Java.

    The first powerful feature is that you have exceptions grouped by
    classes. This means you can group exceptions in a hierarchy; not only a
    tree like but even as a general graph. This feature is present in C++
    and with some restrictions in Java.

    Another feature is that the exception handler is called as a function.
    So if you are in debugger you can see the whole stack frame from the
    point that generated the exception up to the exception handler. So you
    are able to see what were the conditions that made the exception to be
    raised.

    The actual mechanism is based on nested functions, an extension to the C
    language. This extension is currently supported by the GNU C Compiler.
    The actual mechanism is written using macros, so there is no need for
    special support from the compiler.

    A code written using these macros looks like this:

        TRY {
            some code that can generate an exception
        } END_TRY
        CATCH(ExceptionClass1) {
            code to handle an exception of class ExceptionClass1
        }
        CATCH(ExceptionClass2) {
            code to handle an exception of class ExceptionClass2
        }
        ...
        OTHERWISE {
            catch all exceptions not handled above
        }
        END_CATCH


    In the `TRY' block the code that is supposed to generate an exception is
    executed. You can nest `TRY' blocks by entering other blocks of code in
    `TRY' blocks. All `TRY' blocks form a stack with the most recent `TRY'
    block which is executing on the top of the stack.

    If nothing happens during the execution of code inside a `TRY' block,
    the program continues with the first statement after the `END_CATCH'
    label. When this thing happens the topmost `TRY' block is popped off the
    stack.

    To generate an exception you should allocate an exception object and
    pass it to the `THROW' function. This is called raising an exception.
    When an exception is raised the exception handler blocks are searched
    for the one that can `catch' the exception. This means to find the first
    `CATCH' block that match the exception object class. This matching is
    done by sending the exception object the `exceptionIsKindOf:' message
    having as argument the class specified as parameter to `CATCH' block. If
    the result of this message is true then the `CATCH' block matches the
    exception.

    The `exceptionIsKindOf:' method is implemented at the NSException class
    to return the result of `isKindOf:'. So implicitly the exceptions are
    grouped after their inheritance hierarchy. Some specific exception
    classes could implement the `exceptionIsKindOf:' method and simulate a
    graph inheritance, which is like the multiple inheritance in C++.

    Inside the `CATCH' and `OTHERWISE' blocks you have one hidden parameter,
    the exception object, which has the name `exception'. You can do the
    following actions inside an exception handler:

    * you can go immediately after the `END_CATCH' statement if it does not issue any of `RETURN' or `RETRY' statements
    * you can reraise the exception by issuing the `RERAISE' if you want to generate an exception with the same object, or you can use `THROW' to generate an exception with a different object

    You cannot execute a jump with the `goto' statement from the `TRY',
    `CATCH' or `OTHERWISE' blocks outside them. These jumps are permitted
    only locally in the block. Also, do not return from `TRY' or `CATCH'
    blocks with ordinary return statements.

    You can jump outside the `TRY' block with the `BREAK' statement that
    will go to the first statement following the `END_CATCH' statement.

    Another construction allows you to specify a block of code that will be
    executed when an exception is caught by an upper exception handler. This
    allows you to do some cleanup, for example to release all the resources
    acquired from the system (such as memory allocation or file
    descriptors). This block is introduced by the `CLEANUP' label.

    Another construction is the `FINALLY' block. It is equivalent with the
    `finally' block from Java. The code inside this block is called whenever
    either an exception is raised and caught by an upper handler or when the
    code inside a `TRY' block runs successfully.

    The `FINALLY' construct is equivalent with the following `CLEANUP'
    construct:

        TRY {
            some code that can generate an exception
        } END_TRY
        ...
        CLEANUP {
            sequence of code
        }
        END_CATCH
        the same sequence of code from inside the CLEANUP block


    If several exception handlers are nested the order in which the cleanup
    and finally blocks are called is the same with the order in which the
    functions containing them will normally return.

    There are situations when you acquire some resources and you want to be
    sure that they are released in case of an exception that is caught above
    you in the stack frame. So you don't need the `CATCH' or `OTHERWISE'
    blocks. You could simply write:

        TRY {
            some code that can generate an exception
        } END_TRY
        CLEANUP {
            code to release acquired resources
        }
        END_CATCH


    You could use the `FINALLY' construct when the resource is acquired and
    also released in the same function. For example:

        acquire the resource
        TRY {
            some code that can generate an exception
        }
        FINALLY {
            code to release the resource
        }
        END_CATCH


    With these constructions the exception handling macros has the following
    syntax:

        TRY {
            some code that can generate an exception
        } END_TRY
        CATCH(ExceptionClass1) {
            code to handle an exception of class ExceptionClass1
        }
        CATCH(ExceptionClass2) {
            code to handle an exception of class ExceptionClass2
        }
        ...
        OTHERWISE {
            catch all exceptions not handled above
        }
        CLEANUP {
            ...
        }
        FINALLY {
            ...
        }
        END_CATCH


  OpenStep exceptions

    The OpenStep exceptions are defined in the terms of the above macros.

        #define NS_DURING   TRY
        
        #define NS_HANDLER \
            END_TRY \
            OTHERWISE
        
        #define NS_ENDHANDLER       END_CATCH


    In the actual implementation you can also use the `NS_VALRETURN' and
    `NS_VOIDRETURN' macros inside the `TRY' block, respectively inside
    NS_DURING block.

    When you use `NS_VALRETURN' or `NS_VOIDRETURN' macros inside a `TRY'
    block, be aware that before the function returns, the code inside all
    `FINALLY' blocks associated with the `TRY' block are executed first.
    However, because of a bug in the GNU compiler that causes the compiler
    to crash when it compiles Objective-C programs with nested functions for
    the NeXT runtime, this behavior is not performed in the programs
    compiled for the NeXT runtime.

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.