1 | #ifndef EXCEPTION_H
|
2 | #define EXCEPTION_H
|
3 |
|
4 | #include <limits.h>
|
5 | #include <stdbool.h>
|
6 | #include <string.h>
|
7 | #include <setjmp.h>
|
8 |
|
9 | #define BEFORE_AND_AFTER_BLOCK(X,BEFORE,AFTER,T) \
|
10 | for( struct{bool BAAB_V;T;}X={.BAAB_V=true}; X.BAAB_V&&(EX_UNPACK BEFORE); X.BAAB_V=(EX_UNPACK AFTER) )
|
11 |
|
12 | #define EX_UNPACK(...) __VA_ARGS__
|
13 |
|
14 | #define try BEFORE_AND_AFTER_BLOCK( ex_baab, (beginTry(&ex_baab.ex_ejs),!setjmp(ex_baab.ex_ejs.current)||endTry(&ex_baab.ex_ejs)), (endTry(&ex_baab.ex_ejs),false), struct exceptionJmpStorage ex_ejs )
|
15 | #define catch( T, VAR ) \
|
16 | for( struct T##_type* VAR=(struct T##_type*)exception; \
|
17 | catchMatch( T ); exception = (void*)1 )
|
18 | #define finally( VAR ) for( struct exception* VAR=exception; exception&&exception!=(void*)1; (void)VAR,exception=0 )
|
19 | #define throw(T,V) do { \
|
20 | lastException.T = (struct T##_type){ EX_UNPACK V }; \
|
21 | exception = (void*)&lastException; \
|
22 | exception->type = T; \
|
23 | longjmp( *exception_jmp_buf, 1 );\
|
24 | } while(0)
|
25 | #define rethrow() longjmp( *exception_jmp_buf, 1 )
|
26 |
|
27 | struct exception;
|
28 | struct exception {
|
29 | int type;
|
30 | };
|
31 |
|
32 | struct exceptionJmpStorage {
|
33 | jmp_buf* last;
|
34 | jmp_buf current;
|
35 | };
|
36 |
|
37 | extern union anyException lastException;
|
38 | extern struct exception* exception;
|
39 | extern jmp_buf* exception_jmp_buf;
|
40 |
|
41 | void beginTry( struct exceptionJmpStorage* );
|
42 | bool endTry( struct exceptionJmpStorage* );
|
43 | bool catchMatch( int type );
|
44 | bool finallyBefore( void );
|
45 | void finallyAfter( void );
|
46 |
|
47 | #endif
|