82 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #ifndef EXCEPT_INCLUDED
 | |
| #define EXCEPT_INCLUDED
 | |
| 
 | |
| #include <setjmp.h>
 | |
| #define UNUSED(x) (void)(x)
 | |
| 
 | |
| struct Exception {
 | |
| 	const char *reason;
 | |
| };
 | |
| typedef struct Exception Exception;
 | |
| 
 | |
| struct ExceptFrame {
 | |
| 	struct ExceptFrame *prev;   // Exception Stack
 | |
| 	jmp_buf env;                // Enviroment Buffer
 | |
|     	const char *file;           // Exception File
 | |
| 	int line;                   // Exception Line
 | |
| 	const Exception *exception; // Exception Reason
 | |
| };
 | |
| typedef struct ExceptFrame ExceptFrame;
 | |
| 
 | |
| // Exception States 
 | |
| enum { EXCEPT_ENTERED=0, EXCEPT_RAISED, EXCEPT_HANDLED, EXCEPT_FINALIZED};
 | |
| 
 | |
| void except_raise(const Exception *e, const char *file,int line); // Raise exceptions
 | |
| 
 | |
| // External declarations 
 | |
| extern ExceptFrame *except_stack; // Global exception stack
 | |
| extern const Exception assert_failed; // Forward declaration for assert. 
 | |
| extern void asserted(int e);
 | |
| 
 | |
| #ifdef NDEBUG
 | |
| #define ASSERTED(e) ((void)0)
 | |
| #else
 | |
| #define ASSERTED(e) ((void)((e)||(RAISE(assert_failed),0)))
 | |
| #endif
 | |
| 
 | |
| // Raise an Exception.
 | |
| #define RAISE(e) except_raise(&(e), __FILE__, __LINE__)
 | |
| 
 | |
| // Reraise the currect exception.
 | |
| #define RERAISE except_raise(except_frame.exception, \
 | |
| 	except_frame.file, except_frame.line)
 | |
| 
 | |
| // Switch to the previous exception frame and return.
 | |
| #define RETURN switch (except_stack = except_stack->prev,0) default: return
 | |
| 
 | |
| // Start a try block.
 | |
| #define TRY do { \
 | |
| 	volatile int except_flag; \
 | |
| 	ExceptFrame except_frame; \
 | |
| 	except_frame.prev = except_stack; \
 | |
| 	except_stack = &except_frame;  \
 | |
| 	except_flag = setjmp(except_frame.env); \
 | |
| 	if (except_flag == EXCEPT_ENTERED) {
 | |
| 
 | |
| // Handle specific example.
 | |
| #define EXCEPT(e) \
 | |
| 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \
 | |
| 	} else if (except_frame.exception == &(e)) { \
 | |
| 		except_flag = EXCEPT_HANDLED;
 | |
| 
 | |
| // Catch all other exceptions.        
 | |
| #define ELSE \
 | |
| 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \
 | |
| 	} else { \
 | |
| 		except_flag = EXCEPT_HANDLED;
 | |
| 
 | |
| // Execute finalization code.        
 | |
| #define FINALLY \
 | |
| 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \
 | |
| 	} { \
 | |
| 		if (except_flag == EXCEPT_ENTERED) \
 | |
| 			except_flag = EXCEPT_FINALIZED;
 | |
| 
 | |
| // End Try block.         
 | |
| #define END_TRY \
 | |
| 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \
 | |
| 		} if (except_flag == EXCEPT_RAISED) RERAISE; \
 | |
| } while (0)
 | |
| 
 | |
| #endif
 |