exceptions4c  version 2.8
An exception handling framework for C
e4c.h File Reference

exceptions4c header file More...

#include <stdlib.h>
#include <setjmp.h>
#include <stdbool.h>

Data Structures

struct  e4c_exception_type
 Represents an exception type in the exception handling system. More...
struct  e4c_exception
 Represents an instance of an exception type. More...
struct  e4c_signal_mapping
 Represents a map between a signal and an exception. More...

Defines

Exception handling keywords

This set of keywords express the semantics of exception handling.

#define try   E4C_TRY
 Introduces a block of code aware of exceptions.
#define catch(_exception_type_)   E4C_CATCH(_exception_type_)
 Introduces a block of code capable of handling a specific type of exceptions.
#define finally   E4C_FINALLY
 Introduces a block of code responsible for cleaning up the previous exception-aware block.
#define retry(_max_retry_attempts_)   E4C_RETRY(_max_retry_attempts_)
 Repeats the previous try (or use) block entirely.
#define throw(_exception_type_, _message_)   E4C_THROW(_exception_type_, _message_)
 Signals an exceptional situation represented by an exception object.
#define rethrow(_message_)   E4C_RETHROW(_message_)
 Throws again the currently thrown exception, with a new message.
Dispose pattern keywords

This set of keywords express the semantics of automatic resource acquisition and disposal.

#define with(_resource_, _dispose_)   E4C_WITH(_resource_, _dispose_)
 Opens a block of code with automatic disposal of a resource.
#define use   E4C_USE
 Closes a block of code with automatic disposal of a resource.
#define using(_type_, _resource_, _args_)   E4C_USING(_type_, _resource_, _args_)
 Introduces a block of code with automatic acquisition and disposal of a resource.
#define reacquire(_max_reacquire_attempts_)   E4C_REACQUIRE(_max_reacquire_attempts_)
 Repeats the previous with block entirely.
Integration macros

These macros are designed to ease the integration of external libraries which make use of the exception handling system.

#define E4C_VERSION_NUMBER
 Provides the library version number.
#define E4C_VERSION_THREADSAFE
 Provides the library thread mode (either single-thread or multi-thread)
#define E4C_VERSION_MAJOR
 Provides the library major version number.
#define E4C_VERSION_MINOR
 Provides the library minor version number.
#define E4C_VERSION_REVISION
 Provides the library revision number.
#define E4C_VERSION_STRING
 Provides the library version number as a string literal.
#define E4C_EXCEPTION_MESSAGE_SIZE   128
 Provides the maximum length (in bytes) of an exception message.
#define e4c_reusing_context(_status_, _on_failure_)   E4C_REUSING_CONTEXT(_status_, _on_failure_)
 Reuses an existing exception context, otherwise, begins a new one and then ends it.
#define E4C_ON_FAILURE(_handler_)   _handler_( e4c_get_exception() )
 Provides a means of parsing an exception to obtain a status value.
#define E4C_NORETURN
 Marks a function which never returns.
#define E4C_UNREACHABLE_RETURN(_value_)
 Simulates a function return.
Other convenience macros

These macros provide a handy way to: begin (and end) implicitly a new exception context, express assertions, define and declare exceptions, and define arrays of signal mappings.

#define e4c_using_context(_handle_signals_, _uncaught_handler_)   E4C_USING_CONTEXT(_handle_signals_, _uncaught_handler_)
 Introduces a block of code which will use a new exception context.
#define assert(_condition_)   E4C_ASSERT(_condition_)
 Expresses a program assertion.
#define throwf(_exception_type_, _format_,...)
 Throws an exception with a formatted message.
#define rethrowf(_format_,...)
 Throws again the currently thrown exception, with a new, formatted message.
#define E4C_DECLARE_EXCEPTION(_name_)
 Declares an exception type.
#define E4C_DEFINE_EXCEPTION(_name_, _default_message_, _supertype_)
 Defines an exception type.
#define E4C_SIGNAL_MAPPING(_signal_number_, _exception_type_)
 Maps a specific signal number to a given exception type.
#define E4C_IGNORE_SIGNAL(_signal_number_)
 Ignores a specific signal number.
#define E4C_NULL_SIGNAL_MAPPING
 Represents a null signal mapping literal.

Typedefs

typedef void(* e4c_uncaught_handler )(const e4c_exception *exception)
 Represents a function which will be executed in the event of an uncaught exception.

Enumerations

enum  e4c_status { e4c_succeeded, e4c_recovered, e4c_failed }
 Represents the completeness of a code block aware of exceptions. More...

Functions

Exception context handling functions

These functions enclose the scope of the exception handling system and retrieve the current exception context.

bool e4c_context_is_ready (void)
 Checks if the current exception context is ready.
void e4c_context_begin (bool handle_signals, e4c_uncaught_handler uncaught_handler)
 Begins an exception context.
void e4c_context_end (void)
 Ends the current exception context.
void e4c_context_set_signal_mappings (const e4c_signal_mapping *mappings)
 Assigns the specified signal mappings to the exception context.
const e4c_signal_mappinge4c_context_get_signal_mappings (void)
 Retrieves the signal mappings for the current exception context.
e4c_status e4c_get_status (void)
 Returns the completeness status of the executing code block.
const e4c_exceptione4c_get_exception (void)
 Returns the exception that was thrown.
Other integration and convenience functions
long e4c_library_version (void)
 Gets the library version number.
bool e4c_is_instance_of (const e4c_exception *instance, const e4c_exception_type *exception_type)
 Returns whether an exception instance is of a given type.
void e4c_print_exception (const e4c_exception *exception)
 Prints a fatal error message regarding the specified exception.
void e4c_print_exception_type (const e4c_exception_type *exception_type)
 Prints an ASCII graph representing an exception type's hierarchy.

Variables

Predefined signal mappings

There is a predefined set of signal mappings.

Signal mappings are used to convert signals into exceptions.

Common signals are mapped to its corresponding exception, for example:

See also:
e4c_signal_mapping
e4c_context_begin
e4c_context_set_signal_mappings
e4c_context_get_signal_mappings
const e4c_signal_mapping *const e4c_default_signal_mappings
 The array of predefined signal mappings.
Predefined exceptions

Built-in exceptions represent usual error conditions that might occur during the course of any program.

They are organized into a pseudo-hierarchy, being RuntimeException the common supertype of all exceptions.

const e4c_exception_type RuntimeException
 This is the root of the exception pseudo-hierarchy.
const e4c_exception_type NotEnoughMemoryException
 This exception is thrown when the system runs out of memory.
const e4c_exception_type IllegalArgumentException
 This exception is thrown when a function is passed an illegal or inappropriate argument.
const e4c_exception_type AssertionException
 This exception is thrown when an assertion does not hold.
const e4c_exception_type InputOutputException
 This exception is thrown when an input/output error occurs.
const e4c_exception_type SignalException
 This exception is the common supertype of all signal exceptions.
const e4c_exception_type SignalAlarmException
 This exception is thrown when a time limit has elapsed.
const e4c_exception_type SignalChildException
 This exception is thrown when a child process terminates.
const e4c_exception_type SignalTrapException
 This exception is thrown when a condition arises that a debugger has requested to be informed of.
const e4c_exception_type ErrorSignalException
 This exception is the common supertype of all error signal exceptions.
const e4c_exception_type IllegalInstructionException
 This exception is thrown when the process attempts to execute an illegal instruction.
const e4c_exception_type ArithmeticException
 This exception is thrown when the process performs an erroneous arithmetic operation.
const e4c_exception_type BrokenPipeException
 This exception is thrown when the process attempts to write to a broken pipe.
const e4c_exception_type BadPointerException
 This exception is thrown when the process tries to dereference an invalid pointer.
const e4c_exception_type NullPointerException
 This exception is thrown when an unexpected null pointer is found.
const e4c_exception_type ControlSignalException
 This exception is the common supertype of all control signal exceptions.
const e4c_exception_type StopException
 This exception is thrown to stop the process for later resumption.
const e4c_exception_type KillException
 This exception is thrown to terminate the process immediately.
const e4c_exception_type HangUpException
 This exception is thrown when the process' terminal is closed.
const e4c_exception_type TerminationException
 This exception is thrown to request the termination of the process.
const e4c_exception_type AbortException
 This exception is thrown to abort the process.
const e4c_exception_type CPUTimeException
 This exception is thrown when the process has used up the CPU for too long.
const e4c_exception_type UserControlSignalException
 This exception is the common supertype of all control signal exceptions caused by the user.
const e4c_exception_type UserQuitException
 This exception is thrown when the user requests to quit the process.
const e4c_exception_type UserInterruptionException
 This exception is thrown when the user requests to interrupt the process.
const e4c_exception_type UserBreakException
 This exception is thrown when a user wishes to break the process.
const e4c_exception_type ProgramSignalException
 This exception is the common supertype of all user-defined signal exceptions.
const e4c_exception_type ProgramSignal1Exception
 This exception is thrown when user-defined conditions occur.
const e4c_exception_type ProgramSignal2Exception
 This exception is thrown when user-defined conditions occur.

Detailed Description

exceptions4c header file

Version:
2.8
Author:
Copyright (c) 2011 Guillermo Calvo

exceptions4c header file

This header file needs to be included in order to be able to use any of the exception handling system keywords:

In order to stop defining these keywords, there exists a E4C_NOKEYWORDS compile-time parameter. When the keywords are not defined, the next set of alternative macros can be used to achieve the same functionality:

  • E4C_TRY
  • E4C_CATCH
  • E4C_FINALLY
  • E4C_THROW
  • E4C_WITH
  • E4C_USING

License

This is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this software. If not, see <http://www.gnu.org/licenses/>.


Define Documentation

#define assert (   _condition_)    E4C_ASSERT(_condition_)

Expresses a program assertion.

Parameters:
_condition_A predicate that must evaluate to true

An assertion is a mechanism to express that the developer thinks that a specific condition is always met at some point of the program.

assert is a convenient way to insert debugging assertions into a program. The NDEBUG compile-time parameter determines whether the assumptions will be actually verified by the program at run-time.

In presence of NDEBUG, the assertion statements will be ignored and therefore will have no effect on the program, not even evaluating the condition. Therefore expressions passed to assert must not contain side-effects, since they will not take place when debugging is disabled.

In absence of NDEBUG, the assertion statements will verify that the condition is met every time the program reaches that point of the program.

If the assertion does not hold at any time, then an AssertionException will be thrown to indicate the programming error. This exception cannot be caught whatsoever. The program (or current thread) will be terminated.

The main advantage of using this assertion mechanism (as opposed to the macros provided by the standard header file assert.h) is that before actually exiting the program or thread, all of the pending finally blocks will be executed.

Precondition:
A program (or thread) must begin an exception context prior to using the keyword assert. Such programming error will lead to an an abrupt exit of the program (or thread).
See also:
AssertionException
#define catch (   _exception_type_)    E4C_CATCH(_exception_type_)

Introduces a block of code capable of handling a specific type of exceptions.

Parameters:
_exception_type_The type of exceptions to be handled

catch blocks are optional code blocks that must be preceded by try, with... use or using blocks. Several catch blocks can be placed next to one another.

When an exception is thrown, the system looks for a catch block to handle it. The first capable block (in order of appearance) will be executed and the exception is said to be caught.

The caught exception can be accessed through the function e4c_get_exception.

 try{
     ...
 }catch(RuntimeException){
     const e4c_exception * exception = e4c_get_exception();
     printf("Error: %s", exception->message);
 }

The actual type of the exception can be checked against other exception types through the function e4c_is_instance_of.

 try{
     ...
 }catch(RuntimeException){
     const e4c_exception * exception = e4c_get_exception();
     if( e4c_is_instance_of(exception, SignalException.type) ){
         // the exception type is SignalException or any subtype
     }
 }

The type might also be compared directly against another specific exception type.

 try{
     ...
 }catch(RuntimeException){
     const e4c_exception * exception = e4c_get_exception();
     if(exception->type == NotEnoughMemoryException.type){
         // the exception type is precisely NotEnoughMemoryException
     }
 }

After the catch block completes, the finally block (if any) is executed. Then the program continues by the next line following the set of try... catch... finally blocks.

However, if an exception is thrown in a catch block, then the finally block will be executed right away and the system will look for an outter catch block to handle it.

Only one of all the catch blocks will be executed for each try block, even though the executed catch block throws another exception. The only possible way to execute more than one catch block would be by retrying the entire try block.

Precondition:
A catch block must be preceded by one of these blocks:
A catch block must not be exited through any of: goto, break, continue or return (but it is legal to throw an exception).
See also:
try
e4c_exception_type
e4c_get_exception
e4c_exception
e4c_is_instance_of
#define E4C_DECLARE_EXCEPTION (   _name_)
Value:
\
    extern const e4c_exception_type _name_

Declares an exception type.

Parameters:
_name_Name of the exception type

This macro introduces the name of an extern, const exception type which will be available to be thrown or caught:

 E4C_DECLARE_EXCEPTION(StackException);
 E4C_DECLARE_EXCEPTION(StackOverflowException);
 E4C_DECLARE_EXCEPTION(StackUnderflowException);

This macro is intended to be used inside header files.

Note:
When you declare exception types, no storage is allocated. In order to actually define them, you need to use the macro E4C_DEFINE_EXCEPTION.
See also:
e4c_exception_type
E4C_DEFINE_EXCEPTION
#define E4C_DEFINE_EXCEPTION (   _name_,
  _default_message_,
  _supertype_ 
)
Value:
\
    const e4c_exception_type _name_ = { \
        #_name_, \
        _default_message_, \
        &_supertype_ \
    }

Defines an exception type.

Parameters:
_name_Name of the new exception type
_default_message_Default message of the new exception type
_supertype_Supertype of the new exception type

This macro allocates a new, const exception type.

 E4C_DEFINE_EXCEPTION(StackException, "Stack exception", RuntimeException);
 E4C_DEFINE_EXCEPTION(StackOverflowException, "Stack overflow", StackException);
 E4C_DEFINE_EXCEPTION(StackUnderflowException, "Stack underflow", StackException);

This macro is intended to be used inside sorce code files. The defined exception types can be declared in a header file through the macro E4C_DECLARE_EXCEPTION.

See also:
e4c_exception_type
RuntimeException
E4C_DECLARE_EXCEPTION
#define E4C_EXCEPTION_MESSAGE_SIZE   128

Provides the maximum length (in bytes) of an exception message.

#define E4C_IGNORE_SIGNAL (   _signal_number_)
Value:
\
    {_signal_number_, NULL}

Ignores a specific signal number.

Parameters:
_signal_number_Numeric value of the signal to be ignored

This macro represents a signal mapping literal. It comes in handy for initializing arrays of e4c_signal_mapping.

See also:
e4c_signal_mapping
e4c_context_set_signal_mappings
e4c_context_get_signal_mappings
E4C_SIGNAL_MAPPING
E4C_NULL_SIGNAL_MAPPING
E4C_DECLARE_EXCEPTION
#define E4C_NORETURN
Value:
\
    E4C_NORETURN_

Marks a function which never returns.

This macro helps both developer and compiler to assume that the marked function will not return the control to its caller (unless by throwing an exception).

Note:
It does not make sense for these functions to have a return type other than void.

For example, a function f1 that always throws an exception, could be marked with this macro:

 void f1(int foo) E4C_NORETURN;
 // ...
 void f1(int foo){
     if(foo == 1){
         throw(MyException1, "foo is one.");
     }
     throw(MyException2, "foo is not one.");
 }

Then, if another function tested a condition and then called f1, it wouldn't need to return anything witnin the if branch, nor consider the else branch of the test:

 int f2(int bar, int foo){

     if(bar == 0){
         f1(foo);
         // return(-1);
     }// else

     return(123);

 }

If the compiler supports this macro, it could optimize the program and avoid spurious warnings of uninitialized variables.

See also:
E4C_UNREACHABLE_RETURN
#define E4C_NULL_SIGNAL_MAPPING
Value:
\
    {E4C_INVALID_SIGNAL_NUMBER_, NULL}

Represents a null signal mapping literal.

This macro comes in handy for terminating arrays of e4c_signal_mapping.

See also:
e4c_signal_mapping
e4c_context_set_signal_mappings
e4c_context_get_signal_mappings
E4C_SIGNAL_MAPPING
E4C_IGNORE_SIGNAL
E4C_DECLARE_EXCEPTION
#define E4C_ON_FAILURE (   _handler_)    _handler_( e4c_get_exception() )

Provides a means of parsing an exception to obtain a status value.

Parameters:
_handler_The name of the parser function to be called

This is a handy way to call a function when a e4c_reusing_context block fails. This function will be passed the current thrown exception; it is expected to parse it and return a proper status value.

 static int parse_exception(const e4c_exception * exception){

     if(exception->type == &NotEnoughMemoryException){
         return(STATUS_MEMORY_ERROR);
     }else if( is_instance_of(exception, &MyException) ){
         return(STATUS_MY_ERROR);
     }

     return(STATUS_ERROR);
 }

 int library_public_function(void * pointer, int number){

     volatile int status = STATUS_OK;

     e4c_reusing_context(status, E4C_ON_FAILURE(parse_exception)){

         if(pointer == NULL){
             throw(NullPointerException);
         }

         library_private_function(pointer, number);
     }

     return(status);
 }
See also:
e4c_reusing_context
e4c_get_exception
e4c_exception
#define e4c_reusing_context (   _status_,
  _on_failure_ 
)    E4C_REUSING_CONTEXT(_status_, _on_failure_)

Reuses an existing exception context, otherwise, begins a new one and then ends it.

Parameters:
_status_The name of a previously defined variable, or lvalue, which will be assigned the specified failure value
_on_failure_A constant value or expression that will be assigned to the specified lvalue in case of failure

This macro lets library developers use the exception framework, regardless of whether the library clients are unaware of the exception handling system. In a nutshell, function libraries can use try, catch, throw, etc. whether the client previously began an exception context or not.

You must not use this macro unless you are implementing some functionality which is to be called from another program, potentially unaware of exceptions.

When the block completes, the system returns to its previous status (if it was required to open a new exception context, then it will be automatically closed).

This way, when an external functions encounters an error, it may either throw an exception (when the caller is aware of the exception system), or otherwise return an error code (when the caller did not open an exception context).

e4c_reusing_context needs to be given a status variable (or lvalue) that will be assigned a specified failure value when an exception is thrown inside the block. The failure rvalue can be any expression assignable to the specified status lvalue.

 int library_public_function(void * pointer, int number){

     // We don't know where this function is going to be called from, so:
     //   * We cannot use "try", "throw", etc. right here, because the
     //   exception context COULD be uninitialized at this very moment.
     //   * We cannot call "e4c_context_begin" either, because the
     //   exception context COULD be already initialized.
     // If we have to make use of the exception handling system, we need to
     // "reuse" the existing exception context or "use" a new one.

     volatile int status = STATUS_OK;

     e4c_reusing_context(status, STATUS_ERROR){

         // Now we can safely use "try", "throw", etc.
         if(pointer == NULL){
             throw(NullPointerException);
         }

         library_private_function(pointer, number);
     }

     return(status);
 }

The status will be left unmodified if the client (i.e. the function caller) is exception-aware, or the block completes without an error (i.e. no exception is thrown), so it must be properly initialized before returning it.

Please note that the status needs not be just a dichotomy (success or failure). It can be a fine-grained value describing what exactly went wrong. You can pass any expression to e4c_reusing_context wich will be evaluated if an exception is thrown:

 int library_public_function(void * pointer, int number){

     volatile int status = STATUS_OK;
     volatile bool flag = true;

     e4c_reusing_context(status, (flag ? STATUS_NULL_POINTER : STATUS_ERROR)){

         if(pointer == NULL){
             throw(NullPointerException);
         }

         flag = false;

         library_private_function(pointer, number);
     }

     return(status);
 }

However, Most of the times you probably want to yield a different status value depending on the specific exception being thrown. This can be easily accomplished by making use of the macro E4C_ON_FAILURE.

Next, the semantics of e4c_reusing_context are explained, step by step:

  • If there is an exception context at the time the block starts:
    1. The existing exception context will be reused.
    2. The code block will take place.
    3. If any exception is thrown during the execution of the block:
      • It will be propagated upwards to the caller.
      • The control will be transferred to the nearest surrounding block of code which is able to handle that exception.
  • If there is no exception context at the time the block starts:
    1. A new exception context will be begun; note that the signal handling system WILL NOT be set up.
    2. The code block will take place.
    3. If any exception is thrown during the execution of the block:
      • It will be caught.
      • status will be asigned the value of the expression on_failure.

If you need to perform any cleanup, you should place it inside a finally block, for example:

 ...
 e4c_reusing_context(status, STATUS_ERROR){

     void * buffer = NULL;
     try{
         buffer = malloc(1024);
         ...
     }finally{
         free(buffer);
     }
 }
 ...

If you need to rely on the signal handling system, you may call e4c_context_set_signal_mappings explicitly. You should take into account that you could be hijacking your client's original signal mappings, so you should also call e4c_context_get_signal_mappings in order to restore the previous signal mappings when you are done.

 const e4c_signal_mapping new_mappings[] = {
     E4C_SIGNAL_MAPPING(SIGABRT, Exception1),
     E4C_SIGNAL_MAPPING(SIGINT, Exception2),
     E4C_IGNORE_SIGNAL(SIGTERM),
     ...
     E4C_NULL_SIGNAL_MAPPING
 };
 ...
 e4c_reusing_context(status, STATUS_ERROR){

     const e4c_signal_mapping * old_mappings = e4c_context_get_signal_mappings();

     e4c_context_set_signal_mappings(new_mappings);

     try{
         ...
     }finally{
         e4c_context_set_signal_mappings(old_mappings);
     }
 }
 ...

This macro only begins a new exception context if there is no one, already begun, to be used whereas e4c_using_context always attempts to begin a new one.

Precondition:
A block introduced by e4c_reusing_context must not be exited through any of: goto, break, continue or return (but it is legal to throw an exception).
Postcondition:
A block introduced by e4c_reusing_context is guaranteed to take place inside an exception context.
See also:
e4c_context_begin
e4c_context_end
e4c_context_is_ready
e4c_using_context
e4c_exception
E4C_ON_FAILURE
#define E4C_SIGNAL_MAPPING (   _signal_number_,
  _exception_type_ 
)
Value:
\
    {_signal_number_, &_exception_type_}

Maps a specific signal number to a given exception type.

Parameters:
_signal_number_Numeric value of the signal to be converted
_exception_type_Exception type representing the signal

This macro represents a signal mapping literal. It comes in handy for initializing arrays of e4c_signal_mapping.

See also:
e4c_signal_mapping
e4c_context_set_signal_mappings
e4c_context_get_signal_mappings
E4C_IGNORE_SIGNAL
E4C_NULL_SIGNAL_MAPPING
E4C_DECLARE_EXCEPTION
#define E4C_UNREACHABLE_RETURN (   _value_)
Value:
\
    E4C_UNREACHABLE_RETURN_(_value_)

Simulates a function return.

Parameters:
_value_The value that would be returned if the statement took place.

This macro ensures portability on compilers which don't support functions that never return.

Note:
It does not make sense using this macro in void functions.

It may be used after calling a function marked as E4C_NORETURN, so that the compiler will not complain about control reaching end of non-void function. For example:

 void f1(int foo) E4C_NORETURN;

 int f3(int bar, int foo){

     if(bar != 0){
         return(123);
     }

     f1(123);

     E4C_UNREACHABLE_RETURN(-1);
 }

This macro will become an actual return statement if the compiler does not support E4C_NORETURN, even though it will never be reached (because the called function won't actually return control).

See also:
E4C_NORETURN
#define e4c_using_context (   _handle_signals_,
  _uncaught_handler_ 
)    E4C_USING_CONTEXT(_handle_signals_, _uncaught_handler_)

Introduces a block of code which will use a new exception context.

Parameters:
_handle_signals_If true, the signal handling system will be set up with the default mapping.
_uncaught_handler_If not NULL, this function will be called in the event of an uncaught exception.

This macro begins a new exception context to be used by the code block right next to it. When the code completes, e4c_context_end will be called implicitly.

This macro is very convenient when the beginning and the ending of the current exception context are next to each other. For example, there is no semantic difference between this two blocks of code:

 // block 1
 e4c_context_begin (E4C_TRUE, NULL);
 // ...
 e4c_context_end();

 // block 2
 e4c_using_context(E4C_TRUE, NULL){
     // ...
 }

This macro always attempts to begin a new exception context, whereas e4c_reusing_context only does if there is no exception context, already begun, to be used.

This macro should be used whenever possible, rather than doing the explicit, manual calls to e4c_context_begin and e4c_context_end, because it is less prone to errors.

Precondition:
A block introduced by e4c_using_context must not be exited through any of: goto, break, continue or return (but it is legal to throw an exception).
Postcondition:
A block introduced by e4c_using_context is guaranteed to take place inside an exception context.
See also:
e4c_context_begin
e4c_context_end
e4c_reusing_context
#define E4C_VERSION_MAJOR
Value:
\
    E4C_VERSION_(E4C_VERSION_MAJOR_)

Provides the library major version number.

The library major version number is an int value which is incremented from one release to another when there are significant changes in functionality.

See also:
E4C_VERSION_NUMBER
#define E4C_VERSION_MINOR
Value:
\
    E4C_VERSION_(E4C_VERSION_MINOR_)

Provides the library minor version number.

The library minor version number is an int value which is incremented from one release to another when only minor features or significant fixes have been added.

See also:
E4C_VERSION_NUMBER
#define E4C_VERSION_NUMBER
Value:
\
    E4C_VERSION_(E4C_VERSION_NUMBER_)

Provides the library version number.

The library version number is a long value which expresses:

  • library thread mode (either single-thread or multi-thread)
  • library major version number
  • library minor version number
  • library revision number

The multi-thread (or thread-safe) mode can be obtained by compiling the library with the E4C_THREADSAFE compile-time parameter.

The formula to encode these version numbers into a single long value is:

 THREADSAFE * 10000000 + MAJOR * 1000000 + MINOR * 1000 + REVISION

These numbers can be obtained separately through the next macros:

The library version number can be also obtained as a string literal in the format "MAJOR.MINOR.REVISION (THREADSAFE)" through the macro E4C_VERSION_STRING.

Note:
This version number can be considered as the compile-time library version number, as opposed to the run-time library version number (associated with the actual, compiled library). This run-time version number can be obtained through the function e4c_library_version.
Remarks:
The library must be compiled with the corresponding header (i.e. library version number should be equal to header version number).
See also:
e4c_library_version
E4C_VERSION_THREADSAFE
E4C_VERSION_MAJOR
E4C_VERSION_MINOR
E4C_VERSION_REVISION
E4C_VERSION_STRING
#define E4C_VERSION_REVISION
Value:
\
    E4C_VERSION_(E4C_VERSION_REVISION_)

Provides the library revision number.

The library revision number is an int value which is incremented from one release to another when minor bugs are fixed.

See also:
E4C_VERSION_NUMBER
#define E4C_VERSION_STRING
Value:
\
    E4C_VERSION_(E4C_VERSION_STRING_)

Provides the library version number as a string literal.

The format of the string literal is: "MAJOR.MINOR.REVISION (THREADSAFE)".

See also:
E4C_VERSION_NUMBER
#define E4C_VERSION_THREADSAFE
Value:
\
    E4C_VERSION_THREADSAFE_

Provides the library thread mode (either single-thread or multi-thread)

When the library is compiled with the E4C_THREADSAFE compile-time parameter, E4C_VERSION_THREADSAFE will yield the int value 1 (meaning multi-thread mode), otherwise it will yield the int value 0 (meaning single-thread mode).

See also:
E4C_VERSION_NUMBER
#define finally   E4C_FINALLY

Introduces a block of code responsible for cleaning up the previous exception-aware block.

finally blocks are optional code blocks that must be preceded by try, with... use or using blocks. It is allowed to place, at most, one finally block.

The finally block can determine the completeness of the exception-aware block through the function e4c_get_status. The thrown exception (if any) can also be accessed through the function e4c_get_exception.

 try{
    ...
 }finally{
    switch( e4c_get_status() ){

        case e4c_succeeded:
            ...
            break;

        case e4c_recovered:
            ...
            break;

        case e4c_failed:
            ...
            break;
    }
 }

The finally block will be executed only once. The only possible way to be executed again would be by retrying the entire try block.

Precondition:
A finally block must be preceded by a try, with... use, using or catch block.
A finally block must not be exited through any of: goto, break, continue or return (but it is legal to throw an exception).
A program (or thread) must begin an exception context prior to using the keyword finally. Such programming error will lead to an abrupt exit of the program (or thread).
See also:
e4c_exception
e4c_get_exception
e4c_get_status
e4c_status
#define reacquire (   _max_reacquire_attempts_)    E4C_REACQUIRE(_max_reacquire_attempts_)

Repeats the previous with block entirely.

Parameters:
_max_reacquire_attempts_The maximum number of attempts to reacquire

This macro discards any thrown exception (if any) and repeats the previous with block, up to a specified maximum number of attempts. If the acquisition completes, then the use block will be executed.

It is intended to be used in catch or finally blocks, next to a with... use or using block when the resource acquisition failed, as a quick way to fix an error condition and try to acquire the resource again.

 image_type * image;
 const char * image_path = image_get_user_avatar();
 with(image, e4c_image_dispose){
     image = e4c_image_acquire(image_path);
 }use{
     image_show(image);
 }catch(ImageNotFoundException){
     image_path = image_get_default_avatar();
     reacquire(1);
 }
Warning:
If the specified maximum number of attempts is zero, then the with block can eventually be attempted an unlimited number of times. Care should be taken in order not to create an infinite loop.

Once the resource has been acquired, the use block can also be repeated alone through the keyword retry:

 image_type * image;
 const char * image_path = image_get_user_avatar();
 display_type * display = display_get_user_screen();
 with(image, e4c_image_dispose){
     image = e4c_image_acquire(image_path);
 }use{
     image_show(image, display);
 }catch(ImageNotFoundException){
     image_path = image_get_default_avatar();
     reacquire(1);
 }catch(DisplayException){
     display = display_get_default_screen();
     retry(1);
 }
Precondition:
The reacquire keyword must be used from a catch or finally block, preceded by with... use or using blocks.
A program (or thread) must begin an exception context prior to using the keyword reacquire. Such programming error will lead to an abrupt exit of the program (or thread).
Postcondition:
This macro won't return control unless the with block has already been attempted, at least, the specified maximum number of times.
See also:
retry
with
use
#define rethrow (   _message_)    E4C_RETHROW(_message_)

Throws again the currently thrown exception, with a new message.

Parameters:
_message_The new message describing the exception. It should be more specific than the current one

This macro creates a new instance of the thrown exception, with a more specific message.

rethrow is intended to be used in a catch block and the purpose is to refine the message of the currently caught exception. The previous exception (and its message) will be stored as the cause of the newly thrown exception.

 try{
     image = read_file(file_path);
 }catch(FileOpenException){
     rethrow("Image not found.");
 }

The semantics of this keyword are the same as for throw.

Precondition:
A program (or thread) must begin an exception context prior to using the keyword rethrow. Such programming error will lead to an abrupt exit of the program (or thread).
Postcondition:
Control does not return to the rethrow point.
See also:
throw
rethrowf
#define rethrowf (   _format_,
  ... 
)
Value:
\
        E4C_RETHROWF( (_format_), __VA_ARGS__ )

Throws again the currently thrown exception, with a new, formatted message.

Parameters:
_format_The string containing the specifications that determine the output format for the variadic arguments.
...The variadic arguments that will be formatted according to the format control.

This is a handy way to create (and then throw) a new instance of the currently thrown exception, with a more specific, formatted message.

 try{
     image = read_file(file_path);
 }catch(FileOpenException){
     rethrowf("Image '%s' not found.", title);
 }

This macro relies on two features that were introduced in the ISO/IEC 9899:1999 (also known as C99) revision of the C programming language standard in 1999:

  • Variadic macros
  • Buffer-safe function vsnprintf

In order not to create compatibility issues, this macro will only be defined when the __STDC_VERSION__ compile-time parameter is defined as a long value greater than or equal to 199901L, or when HAVE_C99_VARIADIC_MACROS is defined.

The semantics of this keyword are the same as for throw.

Precondition:
A program (or thread) must begin an exception context prior to using the keyword rethrowf. Such programming error will lead to an abrupt exit of the program (or thread).
At least one argument must be passed right after the format string. The message will be composed through the function vsnprintf with the specified format and variadic arguments. For further information on formatting rules, you may look up the specifications for the function vsnprintf.
Postcondition:
Control does not return to the rethrowf point.
See also:
rethrow
throwf
#define retry (   _max_retry_attempts_)    E4C_RETRY(_max_retry_attempts_)

Repeats the previous try (or use) block entirely.

Parameters:
_max_retry_attempts_The maximum number of attempts to retry

This macro discards any thrown exception (if any) and repeats the previous try or use block, up to a specified maximum number of attempts.

This macro is intended to be used within catch or finally blocks as a quick way to fix an error condition and try again.

 const char * file_path = config_get_user_defined_file_path();
 try{
     config = read_config(file_path);
 }catch(ConfigException){
     file_path = config_get_default_file_path();
     retry(1);
     rethrow("Wrong defaults.");
 }
Warning:
If the specified maximum number of attempts is zero, then the block can eventually be attempted an unlimited number of times. Care should be taken in order not to create an infinite loop.

This macro won't return control unless the block has already been attempted, at least, the specified maximum number of times.

Note:
At a catch block, the current exception is considered caught, whether the retry takes place or not. If you want the exception to be propagated when the maximum number of attempts has been reached, then you need to rethrow it again.
 int dividend = 100;
 int divisor = 0;
 int result = 0;
 try{
     result = dividend / divisor;
     do_something(result);
 }catch(RuntimeException){
     divisor = 1;
     retry(1);
     rethrow("Error (not a division by zero).");
 }
Note:
At a finally block, the current exception (if any) will be propagated if the retry does not take place, so you don't need to rethrow it again.
 int dividend = 100;
 int divisor = 0;
 int result = 0;
 try{
     result = dividend / divisor;
     do_something(result);
 }finally{
     if( e4c_get_status() == e4c_failed ){
         divisor = 1;
         retry(1);
         // when we get here, the exception will be propagated
     }
 }
Precondition:
A program (or thread) must begin an exception context prior to using the keyword retry. Such programming error will lead to an abrupt exit of the program (or thread).
The retry keyword must be used from a catch or finally block.
Postcondition:
Control does not return to the retry point, unless the try (or use) block has been attempted, at least, the specified number of times.
See also:
reacquire
try
use
#define throw (   _exception_type_,
  _message_ 
)    E4C_THROW(_exception_type_, _message_)

Signals an exceptional situation represented by an exception object.

Parameters:
_exception_type_The type of exception to be thrown
_message_The ad-hoc message describing the exception. If NULL, then the default message for the specified exception type will be used

Creates a new instance of the specified type of exception and then throws it. The provided message is copied into the thrown exception, so it can be freely deallocated. If NULL is passed, then the default message for that type of exception will be used.

When an exception is thrown, the exception handling framework looks for the appropriate catch block that can handle the exception. The system unwinds the call chain of the program and executes the finally blocks it finds.

When no catch block is able to handle an exception, the system eventually gets to the main function of the program. This situation is called an uncaught exception.

Precondition:
A program (or thread) must begin an exception context prior to using the keyword throw. Such programming error will lead to an abrupt exit of the program (or thread).
Postcondition:
Control does not return to the throw point.
See also:
throwf
rethrow
e4c_exception_type
e4c_exception
e4c_uncaught_handler
e4c_get_exception
#define throwf (   _exception_type_,
  _format_,
  ... 
)
Value:
\
        E4C_THROWF( (_exception_type_), (_format_), __VA_ARGS__ )

Throws an exception with a formatted message.

Parameters:
_exception_type_The type of exception to be thrown
_format_The string containing the specifications that determine the output format for the variadic arguments
...The variadic arguments that will be formatted according to the format control

This is a handy way to compose a formatted message and throw an exception on the fly:

 int bytes = 1024;
 void * buffer = malloc(bytes);
 if(buffer == NULL){
     throwf(NotEnoughMemoryException, "Could not allocate %d bytes.", bytes);
 }

This macro relies on two features that were introduced in the ISO/IEC 9899:1999 (also known as C99) revision of the C programming language standard in 1999:

  • Variadic macros
  • Buffer-safe function vsnprintf

In order not to create compatibility issues, this macro will only be defined when the __STDC_VERSION__ compile-time parameter is defined as a long value greater than or equal to 199901L, or when HAVE_C99_VARIADIC_MACROS is defined.

The semantics of this keyword are the same as for throw.

Precondition:
A program (or thread) must begin an exception context prior to using the keyword throwf. Such programming error will lead to an abrupt exit of the program (or thread).
At least one argument must be passed right after the format string. The message will be composed through the function vsnprintf with the specified format and variadic arguments. For further information on formatting rules, you may look up the specifications for the function vsnprintf.
Postcondition:
Control does not return to the throwf point.
See also:
throw
rethrowf
#define try   E4C_TRY

Introduces a block of code aware of exceptions.

A try statement executes a block of code. If an exception is thrown and there is a catch block that can handle it, then control will be transferred to it. If there is a finally block, then it will be executed, no matter whether the try block completes normally or abruptly, and no matter whether a catch block is first given control.

The block of code immediately after the keyword try is called the try block of the try statement. The block of code immediately after the keyword finally is called the finally block of the try statement.

 stack_t * stack = stack_new();
 try{
     // the try block
     int value = stack_pop(stack);
     stack_push(stack, 16);
     stack_push(stack, 32);
 }catch(StackOverflowException){
     // a catch block
     printf("Could not push.");
 }catch(StackUnderflowException){
     // another catch block
     printf("Could not pop.");
 }finally{
     // the finally block
     stack_delete(stack);
 }

One try block may precede many catch blocks (also called exception handlers). A catch block must have exactly one parameter, which is the exception type it is capable of handling. Within the catch block, the exception can be accessed through the function e4c_get_exception. Exception handlers are considered in left-to-right order: the earliest possible catch block handles the exception. If no catch block can handle the thrown exception, it will be propagated.

Sometimes it can come in handy to retry an entire try block, for instance, once the exception has been caught and the error condition has been solved.

A try block has an associated status according to the way it has been executed:

  • It succeeds when the execution reaches the end of the block without any exceptions.
  • It recovers when an exception is thrown but a catch block handles it.
  • It fails when an exception is thrown and it's not caught.

The status of the current try block can be retrieved through the function e4c_get_status.

Precondition:
A program (or thread) must begin an exception context prior to using the keyword try. Such programming error will lead to an abrupt exit of the program (or thread).
A try block must precede, at least, another block of code, introduced by either catch or finally.
A try block may precede several catch blocks.
A try block can precede, at most, one finally block.
A try block must not be exited through any of: goto, break, continue or return (but it is legal to throw an exception).
Postcondition:
A finally block will be executed after the try block and any catch block that might be executed, no matter whether the try block succeeds, recovers or fails.
See also:
catch
finally
retry
e4c_status
e4c_get_status
#define use   E4C_USE

Closes a block of code with automatic disposal of a resource.

A use block must always be preceded by a with block. These two keywords are designed so the compiler will complain about dangling with... use blocks.

A code block introduced by the use keyword will only be executed when (and if) the acquisition of the resource completes without exceptions.

Either if the use block completes or not, the disposal function will be executed right away.

Precondition:
A use block must be preceded by a with block.
A use block must not be exited through any of: goto, break, continue or return (but it is legal to throw an exception).
See also:
with
#define using (   _type_,
  _resource_,
  _args_ 
)    E4C_USING(_type_, _resource_, _args_)

Introduces a block of code with automatic acquisition and disposal of a resource.

Parameters:
_type_The type of the resource
_resource_The resource to be acquired, used and then disposed
_args_A list of arguments to be passed to the acquisition function

The specified resource will be acquired, used and then disposed. The automatic acquisition and disposal is achieved by calling the magic functions:

  • _type_ e4c_acquire__type_(_args_)
  • void e4c_dispose__type_(_type_ _resource_, E4C_BOOL _failed_)

The resource will be acquired implicitly by assigning to it the result of the magic acquisition function e4c_acquire__type_.

The semantics of the automatic acquisition and disposal are the same as for blocks introduced by with... use. For example, a using block can also precede catch and finally blocks.

Precondition:
A program (or thread) must begin an exception context prior to using the keyword using. Such programming error will lead to an abrupt exit of the program (or thread).
A using block must not be exited through any of: goto, break, continue or return (but it is legal to throw an exception).
See also:
with
#define with (   _resource_,
  _dispose_ 
)    E4C_WITH(_resource_, _dispose_)

Opens a block of code with automatic disposal of a resource.

Parameters:
_resource_The resource to be disposed
_dispose_The name of the disposal function (or macro)

The combination of keywords with... use encapsules the Dispose Pattern. This pattern consists of two separate blocks and an implicit call to a given function:

  1. the with block is responsible for the resource acquisition
  2. the use block makes use of the resource
  3. the disposal function will be called implicitly

A with block must be followed by a use block. In addition, the use block may be followed by catch and finally blocks.

The with keyword guarantees that the disposal function will be called if, and only if, the acquisition block completed without an error (i.e. no exception being thrown from the acquisition block).

If the with block does not complete, neither the disposal function nor the use block will be executed.

The disposal function is called right after the use block. If an exception was thrown, the catch or finally blocks (if any) will take place after the disposal of the resource.

When called, the disposal function will receive two arguments:

  • The resource
  • A boolean flag indicating if the use block did not complete

This way, different actions can be taken depending on the success or failure of the block. For example, commiting or rolling back a transaction resource.

Legacy functions can be reused by defining macros. For example, a file resource needs to be closed regardless of the errors. Since the function fclose only takes one parameter, we could define the next macro:

 # define e4c_dispose_file(_file_, _failed_) fclose(_file_)

Here is the typical usage of with... use:

 with(foo, e4c_dispose_foo){
     foo = e4c_acquire_foo(foobar);
     someAssertion(foo, bar);
     ...
 }use{
     doSomething(foo);
     ...
 }catch(FooAcquisitionFailed){
     recover1();
     ...
 }catch(somethingElseFailed){
     recover2();
     ...
 }finally{
     cleanup();
     ...
 }

Nonetheless, one-liners fit nicely too:

 with(foo, e4c_dispose_foo) foo = e4c_acquire_foo(bar, foobar); use doSomething(foo);

There is a way to lighten up even more this pattern by defining convenience macros, customized for a specific kind of resources. For example, e4c_using_file or e4c_using_memory.

Precondition:
A program (or thread) must begin an exception context prior to using the keyword with. Such programming error will lead to an abrupt exit of the program (or thread).
A with block must not be exited through any of: goto, break, continue or return (but it is legal to throw an exception).
A with block must always be followed by a use block.
See also:
use
using

Typedef Documentation

typedef void(* e4c_uncaught_handler)(const e4c_exception *exception)

Represents a function which will be executed in the event of an uncaught exception.

Parameters:
exceptionThe uncaught exception

These functions are specified when a new exception context is begun:

 void my_uncaught_handler(const e4c_exception * exception){

    printf("Error: %s (%s)\n", exception->name, exception->message);
 }

 int main(int argc, char * argv[]){
     e4c_using_context(E4C_TRUE, my_uncaught_handler){
         // ...
     }
 }

There exists a convenience function to be used as the default uncaught handler, called e4c_print_exception. This function simply prints information regarding the exception to stderr.

Warning:
These functions are not allowed to try and recover the current exception context. Moreover, the program (or current thread) will terminate right after the function returns.
See also:
e4c_context_begin
e4c_using_context
e4c_print_exception

Enumeration Type Documentation

enum e4c_status

Represents the completeness of a code block aware of exceptions.

The symbolic values representing the status of a block help to distinguish between different possible situations inside a finally block. For example, different cleanup actions can be taken, depending on the status of the block.

 try{
    ...
 }finally{
    switch( e4c_get_status() ){

        case e4c_succeeded:
            ...
            break;

        case e4c_recovered:
            ...
            break;

        case e4c_failed:
            ...
            break;
    }
 }
See also:
e4c_get_status
finally
Enumerator:
e4c_succeeded 

There were no exceptions.

e4c_recovered 

There was an exception, but it was caught.

e4c_failed 

There was an exception and it wasn't caught.


Function Documentation

void e4c_context_begin ( bool  handle_signals,
e4c_uncaught_handler  uncaught_handler 
)

Begins an exception context.

Parameters:
handle_signalsIf true, the signal handling system will be set up with the default mapping.
uncaught_handlerIf not NULL, this function will be called in the event of an uncaught exception.

This function begins the current exception context to be used by the program (or current thread), until e4c_context_end is called.

The signal handling system can be initialized automatically with the default signal mapping through the parameter handle_signals. This is equivalent to:

 e4c_context_set_signal_mappings(e4c_default_signal_mappings);
Warning:
Note that, on some specific platforms, the behavior of the standard signal function might be undefined for a multithreaded program, so use the signal handling system with caution.

In addition, a handling function can be specified to be called in the event of an uncaught exception. This function will be called before exiting the program or thread.

There exists a convenience function to be used as the default uncaught handler, called e4c_print_exception. This function simply prints information regarding the exception to stderr.

Precondition:
Once e4c_context_begin is called, the program (or thread) must call e4c_context_end before exiting.
Calling e4c_context_begin twice in a row is considered a programming error, and therefore the program (or thread) will exit abruptly. Nevertheless, e4c_context_begin can be called several times if, and only if, e4c_context_end is called in between.
See also:
e4c_context_end
e4c_context_is_ready
e4c_using_context
e4c_reusing_context
e4c_uncaught_handler
e4c_print_exception
void e4c_context_end ( void  )

Ends the current exception context.

This function ends the current exception context.

Precondition:
A program (or thread) must begin an exception context prior to calling e4c_context_end. Such programming error will lead to an abrupt exit of the program (or thread).
See also:
e4c_context_begin
e4c_context_is_ready
e4c_using_context
e4c_reusing_context
const e4c_signal_mapping* e4c_context_get_signal_mappings ( void  )

Retrieves the signal mappings for the current exception context.

Returns:
The current array of mappings

This function retrieves the current array of mappings between the signals to be handled and the corresponding exception to be thrown.

Precondition:
A program (or thread) must begin an exception context prior to calling e4c_context_get_signal_mappings. Such programming error will lead to an abrupt exit of the program (or thread).
See also:
e4c_context_set_signal_mappings
e4c_signal_mapping
e4c_default_signal_mappings
bool e4c_context_is_ready ( void  )

Checks if the current exception context is ready.

Returns:
Whether the current exception context of the program (or current thread) is ready to be used.

This function returns whether there is an actual exception context ready to be used by the program or current thread.

See also:
e4c_context_begin
e4c_context_end
e4c_using_context
e4c_reusing_context
void e4c_context_set_signal_mappings ( const e4c_signal_mapping mappings)

Assigns the specified signal mappings to the exception context.

Parameters:
mappingsThe array of mappings

This function assigns an array of mappings between the signals to be handled and the corresponding exception to be thrown.

Warning:
Note that, on some specific platforms, the behavior of the standard signal function might be undefined for a multithreaded program, so use the signal handling system with caution.
Precondition:
A program (or thread) must begin an exception context prior to calling e4c_context_set_signal_mappings. Such programming error will lead to an abrupt exit of the program (or thread).
mappings must be terminated by E4C_NULL_SIGNAL_MAPPING.
See also:
e4c_context_get_signal_mappings
e4c_signal_mapping
e4c_default_signal_mappings
const e4c_exception* e4c_get_exception ( void  )

Returns the exception that was thrown.

Returns:
The exception that was thrown in the current exception context (if any) otherwise NULL

This function returns a pointer to the exception that was thrown in the surrounding exception-aware block, if any; otherwise NULL.

The function e4c_is_instance_of will determine if the thrown exception is an instance of any of the defined exception types. The type of the thrown exception can also be compared for an exact type match.

 try{
    ...
 }catch(RuntimeException){
    const e4c_exception * exception = e4c_get_exception();
    if( e4c_is_instance_of(exception, SignalException.type) ){
        ...
    }else if(exception->type == NotEnoughMemoryException.type){
        ...
    }
 }

The thrown exception can be obtained any time, provided that the exception context has begun at the time of the function call. However, it is sensible to call this function only during the execution of finally or catch blocks.

Moreover, a pointer to the thrown exception obtained inside a finally or catch block must not be used from the outside.

The exception system objects are dinamically allocated and deallocated, as the program enters or exits try... catch... finally blocks. While it is legal to copy the thrown exception and access to its name and message outside these blocks, care should be taken in order not to dereference the cause of the exception, unless it is a deep copy (as opposed to a shallow copy).

Precondition:
A program (or thread) must begin an exception context prior to calling e4c_get_exception. Such programming error will lead to an abrupt exit of the program (or thread).
See also:
e4c_exception
e4c_is_instance_of
throw
catch
finally
e4c_status e4c_get_status ( void  )

Returns the completeness status of the executing code block.

Returns:
The completeness status of the executing code block

Exception-aware code blocks have a completeness status regarding the exception handling system. This status determines whether an exception was actually thrown or not, and whether the exception was caught or not.

The status of the current block can be obtained any time, provided that the exception context has begun at the time of the function call. However, it is sensible to call this function only during the execution of finally blocks.

Precondition:
A program (or thread) must begin an exception context prior to calling e4c_get_status. Such programming error will lead to an abrupt exit of the program (or thread).
See also:
e4c_get_status
finally
bool e4c_is_instance_of ( const e4c_exception instance,
const e4c_exception_type exception_type 
)

Returns whether an exception instance is of a given type.

Parameters:
instanceThe thrown exception
exception_typeA previously defined type of exceptions
Returns:
Whether the specified exception is an instance of the given type

e4c_is_instance_of can be used to determine if a thrown exception is an instance of a given exception type.

This macro is intended to be used in a catch block, or in a finally block provided that some exception was actually thrown (i.e. e4c_get_status returned e4c_failed or e4c_recovered).

 try{
    ...
 }catch(RuntimeException){
    const e4c_exception * exception = e4c_get_exception();
    if( e4c_is_instance_of(exception, SignalException.type) ){
        ...
    }else if(exception->type == NotEnoughMemoryException.type){
        ...
    }
 }
Precondition:
instance must not be NULL
type must not be NULL
Exceptions:
NullPointerExceptionIf either instance or type is NULL
See also:
e4c_exception
e4c_exception_type
e4c_get_exception
long e4c_library_version ( void  )

Gets the library version number.

Returns:
The version number associated with the library

This function provides the same information as the E4C_VERSION_NUMBER macro, but the returned version number is associated with the actual, compiled library.

Note:
This version number can be considered as the run-time library version number, as opposed to the compile-time library version number (specified by the header file).
Remarks:
The library must be compiled with the corresponding header (i.e. library version number should be equal to header version number).
See also:
E4C_VERSION_NUMBER
void e4c_print_exception ( const e4c_exception exception)

Prints a fatal error message regarding the specified exception.

Parameters:
exceptionThe uncaught exception

This is a convenience function for showing an error message through the standard error output. It can be passed to e4c_context_begin or e4c_using_context as the handler for uncaught exceptions.

In absence of NDEBUG, this function prints as much information regarding the exception as it is available, whereas in presence of NDEBUG, only the name and message of the exception are printed.

Precondition:
exception must not be NULL
Exceptions:
NullPointerExceptionIf exception is NULL
See also:
e4c_uncaught_handler
e4c_context_begin
e4c_using_context
void e4c_print_exception_type ( const e4c_exception_type exception_type)

Prints an ASCII graph representing an exception type's hierarchy.

Parameters:
exception_typeAn exception type

This is a convenience function for showing an ASCII graph representing an exception type's hierarchy through the standard error output.

For example, the output for ProgramSignal2Exception would be:


	Exception hierarchy
	________________________________________________________________

	    RuntimeException
	     |
	     +--SignalException
	         |
	         +--ProgramSignalException
	             |
	             +--ProgramSignal2Exception
	________________________________________________________________

Precondition:
exception_type must not be NULL
Exceptions:
NullPointerExceptionIf exception_type is NULL
See also:
e4c_exception_type

Variable Documentation

This exception is thrown to abort the process.

AbortException represents SIGABRT, the signal sent by computer programs to abort the process.

Extends:
ControlSignalException

This exception is thrown when the process performs an erroneous arithmetic operation.

ArithmeticException represents SIGFPE, the signal sent to a process when it performs an erroneous arithmetic operation.

Extends:
ErrorSignalException

This exception is thrown when an assertion does not hold.

AssertionException is part of the assertion facility of the library. It is thrown when the compile-time parameter NDEBUG is present and the conditon of an assertion evaluates to false.

Remarks:
This exception cannot be caught whatsoever. The program (or current thread) will be terminated, after the execution of all pending finally blocks.
See also:
assert

This exception is thrown when the process tries to dereference an invalid pointer.

BadPointerException represents SIGSEGV, the signal sent to a process when it makes an invalid memory reference, or segmentation fault.

Extends:
ErrorSignalException
Direct known subexceptions:
NullPointerException

This exception is thrown when the process attempts to write to a broken pipe.

BrokenPipeException represents SIGPIPE, the signal sent to a process when it attempts to write to a pipe without a process connected to the other end.

Extends:
ErrorSignalException

This exception is the common supertype of all control signal exceptions.

Control signal exceptions are thrown when the process needs to be controlled by the user or some other process.

Extends:
SignalException
Direct known subexceptions:
StopException, KillException, HangUpException, TerminationException, AbortException, CPUTimeException, UserControlSignalException

This exception is thrown when the process has used up the CPU for too long.

CPUTimeException represents SIGXCPU, the signal sent to a process when it has used up the CPU for a duration that exceeds a certain predetermined user-settable value.

Extends:
ControlSignalException

The array of predefined signal mappings.

This exception is the common supertype of all error signal exceptions.

Error signal exceptions are thrown when some error prevents the program to keep executing its normal flow.

Extends:
SignalException
Direct known subexceptions:
IllegalInstructionException, BadPointerException, ArithmeticException, BrokenPipeException

This exception is thrown when the process' terminal is closed.

HangUpException represents SIGHUP, the signal sent to a process when its controlling terminal is closed.

Extends:
ControlSignalException

This exception is thrown when a function is passed an illegal or inappropriate argument.

IllegalArgumentException is thrown by a function when it detects that some of the function parameters (passed by the caller) is unacceptable.

Extends:
RuntimeException

This exception is thrown when the process attempts to execute an illegal instruction.

IllegalInstructionException represents SIGILL, the signal sent to a process when it attempts to execute a malformed, unknown, or privileged instruction.

Extends:
ErrorSignalException

This exception is thrown when an input/output error occurs.

InputOutputException is the general type of exceptions produced by failed or interrupted I/O operations.

Extends:
RuntimeException
Direct known subexceptions:
FileException

This exception is thrown to terminate the process immediately.

KillException represents SIGKILL, the signal sent to a process to cause it to terminate immediately.

Remarks:
Since SIGKILL is usually unblock-able, it won't be handled and converted to this exception automatically on some platforms.
Extends:
ControlSignalException

This exception is thrown when the system runs out of memory.

NotEnoughMemoryException is thrown when there is not enough memory to continue the execution of the program.

Extends:
RuntimeException

This exception is thrown when an unexpected null pointer is found.

NullPointerException is thrown when some part of the program gets a pointer which was expected or required to contain a valid memory address.

A null pointer exception is a special case of a bad pointer exception. The difference between them is that NullPointerException needs to be thrown explicitly by some function, while BadPointerException is thrown implicitly by the signal handling system.

Note:
Sometimes, a null pointer exception can also be considered as a special case of an illegal argument exception.
Extends:
BadPointerException
See also:
IllegalArgumentException

This exception is thrown when user-defined conditions occur.

ProgramSignal1Exception represents SIGUSR1, the signal sent to a process to indicate user-defined conditions.

Extends:
ProgramSignalException

This exception is thrown when user-defined conditions occur.

ProgramSignal2Exception represents SIGUSR1, the signal sent to a process to indicate user-defined conditions.

Extends:
ProgramSignalException

This exception is the common supertype of all user-defined signal exceptions.

User-defined signal exceptions are thrown to indicate user-defined conditions.

Extends:
SignalException
Direct known subexceptions:
ProgramSignal1Exception, ProgramSignal2Exception

This is the root of the exception pseudo-hierarchy.

RuntimeException is the common supertype of all exceptions.

Direct known subexceptions:
NotEnoughMemoryException, AssertionException, IllegalArgumentException, InputOutputException, SignalException

This exception is thrown when a time limit has elapsed.

SignalAlarmException represents SIGALRM, the signal sent to a process when a time limit has elapsed.

Extends:
SignalException

This exception is thrown when a child process terminates.

SignalChildException represents SIGCHLD, the signal sent to a process when a child process terminates.

Extends:
SignalException

This exception is the common supertype of all signal exceptions.

Signal exceptions are thrown when some signal is sent to the process.

A signal can be generated by calling raise.

Extends:
RuntimeException
Direct known subexceptions:
SignalException, SignalAlarmException, SignalChildException, SignalTrapException, ErrorSignalException, ControlSignalException, ProgramSignalException

This exception is thrown when a condition arises that a debugger has requested to be informed of.

SignalTrapException represents SIGTRAP, the signal sent to a process when a condition arises that a debugger has requested to be informed of.

Extends:
SignalException

This exception is thrown to stop the process for later resumption.

StopException represents SIGSTOP, the signal sent to a process to stop it for later resumption.

Remarks:
Since SIGSTOP is usually unblock-able, it won't be handled and converted to this exception automatically on some platforms.
Extends:
ControlSignalException

This exception is thrown to request the termination of the process.

TerminationException represents SIGTERM, the signal sent to a process to request its termination.

Extends:
ControlSignalException

This exception is thrown when a user wishes to break the process.

UserBreakException represents SIGBREAK, the signal sent to a process by its controlling terminal when a user wishes to break it.

Extends:
UserControlSignalException

This exception is the common supertype of all control signal exceptions caused by the user.

User control signal exceptions are thrown when the process needs to be controlled by the user.

Extends:
ControlSignalException
Direct known subexceptions:
UserQuitException, UserInterruptionException, UserBreakException

This exception is thrown when the user requests to interrupt the process.

UserInterruptionException represents SIGINT, the signal sent to a process by its controlling terminal when a user wishes to interrupt it.

Extends:
UserControlSignalException

This exception is thrown when the user requests to quit the process.

UserQuitException represents SIGQUIT, the signal sent to a process by its controlling terminal when the user requests that the process dump core.

Extends:
UserControlSignalException