/**\file n_exceptions.h
 * Exception management for C
 *\author Castagnier Mickael
 *\version 1.0
 *\date 20/11/09
 */
#ifndef ____EXCEPTION___MANAGEMENT__FOR_C
#define ____EXCEPTION___MANAGEMENT__FOR_C

#ifdef __cplusplus
extern "C"
{
#endif

/**\defgroup EXCEPTION EXCEPTION: C++ style try,catch,endtry,throw
   \addtogroup EXCEPTION 
  @{
*/

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include "n_log.h"

   /*! Possibly Throwed value, everything is fine */
#define NO_EXCEPTION		0		
   /*! Possibly Throwed value, we checked an out of bound operation */
#define ARRAY_EXCEPTION		2		
   /*! Possibly Throwed value, we check a divide by zero operation */
#define DIVZERO_EXCEPTION	4	
   /*! Possibly Throwed value, we checked an overflow in our arrays */
#define OVERFLOW_EXCEPTION	8		
   /*! Possibly Throwed value, we checked an error during a char * parsing */
#define PARSING_EXCEPTION	16
   /*! General exception, we just detected an error an decided to go back where we're safe */
#define GENERAL_EXCEPTION	ARRAY_EXCEPTION|DIVZERO_EXCEPTION|OVERFLOW_EXCEPTION|PARSING_EXCEPTION

   /*! Exception stack structure */
   typedef struct ExceptionContextList
   {
      /*! saving the current context */
      jmp_buf context;
      /*! pointer to the next stacked exception */
      struct ExceptionContextList* head;
   }ExceptionContextList;

   /*! Globale variable for exception stack management */
   extern ExceptionContextList *__Exceptions;

   /*	Add an exception in the stack */
   void push_exception(void);
   /*	Pop an exceptions from the stack */
   void pop_exception(int);

   /*! Macro for replacing try */
#define Try							\
   {							\
      int __exc_ ;					\
      push_exception();				\
      __exc_ = setjmp( __Exceptions -> context );	\
      if( __exc_ == NO_EXCEPTION ) 			\
      {						
     /*! Macro for replacing catch */
#define Catch(X)	 		\
      }			\
      if( __exc_ & (X) )	\
      {			\
         __exc_ = 0 ;	

     /*! Macro helper for closing the try-catch block */
#define EndTry 					\
      }				\
      pop_exception( __exc_ );\
   }

   /*! Macro helper for adding exception throwing in custom functions */
#define Throw(X) \
   longjmp( __Exceptions -> context , (X) )

/*@}*/   
   
#ifdef __cplusplus
}
#endif


#endif /* #ifndef ____EXCEPTION___MANAGEMENT__FOR_C  */
