/** exceptions2.c -- by James Lin (2001-05-19)
  *    a set of macros to simulate exception handling
  *
  *    This version is more like the try/catch syntax used in Java, where
  *    each exception type has a separate catch block.  It is, however,
  *    less flexible.
  *
  * Copyright (c) 2001 James Lin
  * This code may be modified freely, provided that this copyright notice
  * remains intact and is clearly visible in all derivative works.
  */

/** Exception-handling syntax:
  *     TRY
  *     {   ...
  *     }
  *     CATCH_BEGIN
  *         CATCH(<E1>)
  *         {   ...
  *         }
  *         CATCH(<E2>)
  *         {   ...
  *         }
  *
  *         ...
  *
  *         CATCH_DEFAULT   // optional
  *         {   ...
  *         }
  *
  *         CATCH_COMMON    // optional
  *         {   ...
  *         }
  *     CATCH_END           // no trailing semicolon
  *
  * Exception-throwing syntax:
  *     THROW(<E>);
  *     RETHROW();          // re-throw the current exception
  *
  * Notes:
  *     Exceptions are represented as ints.
  *
  *     If neither CATCH_DEFAULT nor CATCH_COMMON is present, any uncaught
  *     exception will be re-thrown.
  *
  *     Order matters; CATCH blocks must appear before CATCH_DEFAULT, and
  *     CATCH_DEFAULT must appear before CATCH_COMMON.
  *
  *     Code that uses these TRY/CATCH/THROW macros must not use the
  *     following variables:
  *         _cur_exception
  *         _old_exception_env
  *
  *     Local, automatic variables modified within a TRY block should be
  *     declared as volatile.
  *
  *     This is non-portable.  Works with gcc but apparently not with MSVC.
  */

#ifndef JDL_EXCEPTIONS_C
#define JDL_EXCEPTIONS_C

#include <setjmp.h>

#if DEBUG > 1
    #include <stdio.h>
#endif



/* TYPEDEFS ------------------------------------------------------------ */

typedef struct
{   jmp_buf env;
    int err;

#if DEBUG > 0
    char* file;
    unsigned int line;
#endif
} exception_t;



/* MACROS -------------------------------------------------------------- */

/* this macro may not be portable */
#define JMP_BUF_COPY(jbDest, jbSrc) (*(jbDest) = *(jbSrc))

#define TRY \
    {   jmp_buf _old_exception_env; \
        JMP_BUF_COPY(_old_exception_env, _cur_exception.env); \
        if ((_cur_exception.err = setjmp(_cur_exception.env)) == 0) \
        {

#define CATCH_BEGIN \
           JMP_BUF_COPY(_cur_exception.env, _old_exception_env); \
        } \
        else \
        {  JMP_BUF_COPY(_cur_exception.env, _old_exception_env); \
           if (0) { }

#define CATCH(e) \
           else if (_cur_exception.err == (e))

#define CATCH_DEFAULT \
           else if (1)

#define CATCH_COMMON \
           if (1)

#define CATCH_END \
           else \
           {  RETHROW(); \
           } \
        } \
    }

#if DEBUG > 0
    #if DEBUG > 1
        #define THROW(e) \
            (_cur_exception.file = __FILE__, \
             _cur_exception.line = __LINE__, \
             fprintf(stderr, \
                     "throwing exception %u (" __FILE__ ", %u)\n", \
                     (e), __LINE__), \
             longjmp(_cur_exception.env, (e)))
    #else
        #define THROW(e) \
            (_cur_exception.file = __FILE__, \
             _cur_exception.line = __LINE__, \
             longjmp(_cur_exception.env, (e)))
    #endif
#else
    #define THROW(e) (longjmp(_cur_exception.env, (e)))
#endif

#define RETHROW() THROW(_cur_exception.err)



/* GLOBALS ------------------------------------------------------------- */

exception_t _cur_exception;



#endif



                                                             ... more stuff
___________________________________________________________________________
page updated: (see above)                      home . about . stuff . links
copyright (c) 2001 james lin