The Exception Handling Library  0.2.1
Defines | Enumerations | Variables
except.h File Reference

Documentation for Exception Handling Library (CBL) More...

#include <setjmp.h>
Include dependency graph for except.h:
This graph shows which files directly or indirectly include this file:

Defines

#define EXCEPT_RAISE(e)   except_raise(&(e), __FILE__, __LINE__)
 raises exception e.
#define EXCEPT_RERAISE   except_raise(except_frame.exception, except_frame.file, except_frame.line)
 raises the exception again that has been raised most recently.
#define EXCEPT_RETURN   switch(except_stack=except_stack->prev, 0) default: return
 returns to the caller function within a TRY-EXCEPT statement.
#define EXCEPT_TRY
 starts a TRY statement.
#define EXCEPT_EXCEPT(e)
 starts an EXCEPT(e) clause.
#define EXCEPT_ELSE
 starts an ELSE clause.
#define EXCEPT_FINALLY
 starts a FINALLY clause.
#define EXCEPT_END
 ends a TRY-EXCEPT or TRY-FINALLY statement.

Enumerations

enum  { EXCEPT_ENTERED = 0, EXCEPT_RAISED, EXCEPT_HANDLED, EXCEPT_FINALIZED }

Functions

exception raising functions:
void except_raise (const except_t *, const char *, int)
 raises an exception and set its information properly.

Variables

except_frame_t * except_stack
 stack for handling nested exceptions.

Detailed Description

Documentation for Exception Handling Library (CBL)

Header for Exception Handling Library (CBL)


Define Documentation

#define EXCEPT_ELSE
Value:
if (except_flag == EXCEPT_ENTERED)        \
                        except_stack = except_stack->prev;    \
                } else {                                      \
                    except_flag = EXCEPT_HANDLED;

starts an ELSE clause.

If there is no matched EXCEPT clause for a raised exception the control moves to the statements following the ELSE clause.

#define EXCEPT_END
Value:
if (except_flag == EXCEPT_ENTERED)        \
                        except_stack = except_stack->prev;    \
                }                                             \
                if (except_flag == EXCEPT_RAISED)             \
                    EXCEPT_RERAISE;                           \
            }

ends a TRY-EXCEPT or TRY-FINALLY statement.

If a raised exception is not handled by the current handler, it will be handled by the previous handler if any.

#define EXCEPT_EXCEPT (   e)
Value:
if (except_flag == EXCEPT_ENTERED)          \
                        except_stack = except_stack->prev;      \
                } else if (except_frame.exception == &(e)) {    \
                    except_flag = EXCEPT_HANDLED;

starts an EXCEPT(e) clause.

When an exception e is raised, its following statements are executed. Finishing them moves the control to the end of the TRY statement.

#define EXCEPT_FINALLY
Value:
if (except_flag == EXCEPT_ENTERED)        \
                        except_stack = except_stack->prev;    \
                }                                             \
                {                                             \
                    if (except_flag == EXCEPT_ENTERED)        \
                        except_flag = EXCEPT_FINALIZED;

starts a FINALLY clause.

It is used to construct a TRY-FINALLY statement, which is useful when some clean-up is necessary before exiting the TRY-FINALLY statement; the statements under the FINALLY clause are executed whether or not an exception occurs. EXCEPT_RERAISE macro can be used to hand over the not-yet-handled exception to the previous handler.

Warning:
Remember that, since raising an exception pops up the execption stack, re-raising an exception in a FINALLY clause has the effect to move the control to the outer (previous) handler. Also note that, even if not explicitly specified, a TRY-EXCEPT-FINALLY statement (there are both EXCEPT and FINALLY clauses) is possible and works as expected.
#define EXCEPT_RETURN   switch(except_stack=except_stack->prev, 0) default: return

returns to the caller function within a TRY-EXCEPT statement.

In order to maintain the stack handling nested exceptions, the ordinary return statement should be avoided in statements following EXCEPT_TRY (referred to as S below; see the explanation for EXCEPT_TRY). Because return has no idea about the exception frame, retruning without using EXCEPT_RETURN from S spoils the exception stack. EXCEPT_RETURN adjusts the stack properly by popping the current exception frame before returning to the caller.

Warning:
Note that the current exception frame is popped when an exception occurs during execution of S and before the control moves to one of EXCEPT, ELSE and FINALLY clauses, which means using EXCEPT_RETURN there is not allowed since it affects the previous, not the current, exception frame.
#define EXCEPT_TRY
Value:
{                                                  \
                volatile int except_flag;                      \
                /* volatile */ except_frame_t except_frame;    \
                except_frame.prev = except_stack;              \
                except_stack = &except_frame;                  \
                except_flag = setjmp(except_frame.env);        \
                if (except_flag == EXCEPT_ENTERED) {

starts a TRY statement.

Statements (referred to as S hereafter) whose exception is to be handled in EXCEPT, ELSE or FINALLY clause follow.

Warning:
Do not forget using EXCEPT_RETURN when returning from S. See EXCEPT_RETURN for more details. Besides, the TRY-EXCEPT/FINALLY statement uses the non-local jump mechanism provided by <setjmp.h>, which means any restriction applied to <setjmp.h> also applies to the TRY-EXCEPT/FINALLY statement. For example, the standard does not guarantee that an automatic non-volatile variable belonging to the function which contains setjmp() preserves its last stored value when it is updated between a call to setjmp() and a call to longjmp() with the same jmp_buf.

Enumeration Type Documentation

anonymous enum
Enumerator:
EXCEPT_ENTERED 

exception handling started and no exception raised yet

EXCEPT_RAISED 

exception raised and not handled yet

EXCEPT_HANDLED 

exception handled

EXCEPT_FINALIZED 

exception finalized


Function Documentation

void except_raise ( const except_t *  e,
const char *  file,
int  line 
)

raises an exception and set its information properly.

EXCEPT_RAISE and EXCEPT_RERAISE macros call except_raise() with __FILE__ and __LINE__ predefined macros (and __func__ if C99 supported) for the file and line parameters. In general there is little chance to call except_raise() directly from application code.

Possible exceptions: assert_exceptfail

Unchecked errors: foreign data structure given for e

Parameters:
[in]eexception to raise
[in]filefile name where exception occurred
[in]funcfunction name where exception occurred (if C99 supported)
[in]lineline number where exception occurred
Returns:
except_raise() cannot return anything
Todo:
Improvements are possible and planned:
  • it would be useful to show stack traces when an uncaught exception leads to abortion of a program. The stack traces should include as much information as possible, for example, names of caller functions, calling sites (file name, function name and line number) and arguments.
 All Files Functions Variables Enumerator Defines