1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
/* -*- Mode: C; c-file-style: "bsd" -*- */
#ifndef YEXCEP_H
#define YEXCEP_H
/* yes, macros with gotos in them, but in the interests of
* avoiding repetition of code, and having less error prone
* error handling
*
* EXCEP_DECL - declares the return value and local state variables
* needed by the exception macros
*
* THROW( x ) - set return value to x and goto function cleanup
* section (CATCH: block). In the catch block, THROW
* does not goto catch label to avoid loops, and instead
* falls through to the next statement.
*
* EXCEP_OK - success return value (=1)
*
* EXCEP_FAIL - failure return value (=0), other user exceptions are
* given negative values (<0)
*
* TRY( x ) - if code returns value <= 0 TRY sets return value to
* that value and goes to function cleanup section
* (CATCH: block). In the catch block, TRY does not goto
* the catch label to avoid loops, and instead
* falls through to the next statement. The
* return value is set to the first non success value
* returned by a TRY, unless this is overridden by a THROW.
*
* CATCH: - start of catch block, also switches behavior of
* TRY and THROW to not goto CATCH: inside the catch
* block to avoid loops
*
* EXCEP_RET - return the current return value from the function
* equivlanet to return (EXCEPTION)
*
* EXCEPTION - current return value, is set to EXCEP_OK by EXCEP_DECL
*
* EXCEP_BOOL - convert current return value to EXCEP_OK, or EXCEP_FAIL
* (EXCEP_FAIL is anything other than EXCEP_OK)
*
*/
/* example usage */
/*
*
* #define EXCEP_OK_COMMENT 2
* #define EXCEP_NULL_PTR -1
* #define EXCEP_OUT_OF_MEM -2
*
* int bar( char *c )
* {
* EXCEP_DECL;
*
* if ( !c ) { THROW( EXCEP_NULL_PTR ); }
* if ( *c == '\0' ) { THROW( EXCEP_FAIL ); );
* if ( *c == '#' ) { SET( EXCEP_COMMENT ); }
* CATCH:
* EXCEP_RET;
* }
*
* int foo( char *c )
* {
* EXCEP_DECL;
* int *p = NULL;
*
* if ( !c ) { THROW( EXCEP_NULL_PTR ); }
* TRY( bar( c ) );
* if ( RETURN == EXCEP_COMMENT ) { print( "comment\n" ); }
* p = strdup( c );
* if ( !p ) { THROW( EXCEP_OUT_OF_MEM ); }
*
* CATCH:
* if ( p ) { TRY( bar( p ) ); free( p ); }
* THROW( EXCEP_BOOL );
* if ( EXCEPTION == EXCEP_OK ) { printf( "success\n" ); }
* EXCEP_RET;
* }
*
*/
#define EXCEP_FAIL 0
#define EXCEP_OK 1
#define EXCEP_DECL int _thr = 0, _ret2 = 0, _ret = _ret2+EXCEP_OK
#define THROW( x ) \
do { \
_ret = (x); \
if( !_thr ) { goto _catch; } \
} while ( 0 )
#define TRY( x ) \
do { \
_ret2 = (x); \
if ( _ret > 0 && _ret2 <= 0 ) { THROW( _ret2 ); } \
} while ( 0 )
#define SET( x ) (_ret = (x))
#define EXCEP_RET return( _ret )
#define EXCEPTION _ret
#define RETURN _ret2
#define CATCH _catch: _thr = 1; if ( 0 ) { goto _foo; } _foo
#define EXCEP_BOOL ( _ret > 0 ? EXCEP_OK : EXCEP_FAIL )
#endif
|