Index: ossp-pkg/ex/ex.h RCS File: /v/ossp/cvs/ossp-pkg/ex/ex.h,v rcsdiff -q -kk '-r1.11' '-r1.12' -u '/v/ossp/cvs/ossp-pkg/ex/ex.h,v' 2>/dev/null --- ex.h 2002/01/29 20:10:53 1.11 +++ ex.h 2002/01/30 10:33:36 1.12 @@ -96,17 +96,19 @@ __ex_mctx_t *ctx_mctx; /* permanent machine context of enclosing try/catch */ int ctx_disabled; /* permanent flag whether exception handling is disabled */ int ctx_caught; /* temporary flag whether exception was caught */ + int ctx_cleanup; /* temporary flag whether cleanup block was present */ volatile ex_t ctx_ex; /* temporary exception storage */ } ex_ctx_t; /* the static and dynamic initializers for a context structure */ #define EX_CTX_INITIALIZER \ - { NULL, 0, 0, { NULL, NULL, NULL, NULL, 0, NULL } } + { NULL, 0, 0, 0, { NULL, NULL, NULL, NULL, 0, NULL } } #define EX_CTX_INITIALIZE(ctx) \ do { \ (ctx)->ctx_mctx = NULL; \ (ctx)->ctx_disabled = 0; \ (ctx)->ctx_caught = 0; \ + (ctx)->ctx_cleanup = 0; \ (ctx)->ctx_ex.ex_class = NULL; \ (ctx)->ctx_ex.ex_object = NULL; \ (ctx)->ctx_ex.ex_value = NULL; \ @@ -133,11 +135,12 @@ __ex_mctx_t __ex_mctx_me; \ __ex_mctx_en = __ex_ctx_ptr->ctx_mctx; \ __ex_ctx_ptr->ctx_mctx = &__ex_mctx_me; \ + __ex_ctx_ptr->ctx_cleanup = 0; \ if (__ex_mctx_save(&__ex_mctx_me)) { \ if (1) -/* the block for catching an exception */ -#define ex_catch(e) \ +/* the optional(!) block for cleanup */ +#define ex_cleanup \ else { \ } \ __ex_ctx_ptr->ctx_caught = 0; \ @@ -147,6 +150,24 @@ __ex_ctx_ptr->ctx_caught = 1; \ } \ __ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \ + __ex_ctx()->ctx_cleanup = 1; \ + if (1) { \ + if (1) + +/* the block for catching an exception */ +#define ex_catch(e) \ + else { \ + } \ + if (!(__ex_ctx()->ctx_cleanup)) \ + __ex_ctx_ptr->ctx_caught = 0; \ + } \ + else { \ + if (!(__ex_ctx()->ctx_cleanup)) { \ + __ex_mctx_restored(&__ex_mctx_me); \ + __ex_ctx_ptr->ctx_caught = 1; \ + } \ + } \ + __ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \ } \ if ( !(__ex_ctx()->ctx_caught) \ || ((e) = __ex_ctx()->ctx_ex, 0)) { \ Index: ossp-pkg/ex/ex.pod RCS File: /v/ossp/cvs/ossp-pkg/ex/ex.pod,v rcsdiff -q -kk '-r1.9' '-r1.10' -u '/v/ossp/cvs/ossp-pkg/ex/ex.pod,v' 2>/dev/null --- ex.pod 2002/01/29 20:10:53 1.9 +++ ex.pod 2002/01/30 10:33:36 1.10 @@ -36,13 +36,13 @@ B I; -B { ... } B (I) { ... } +B {...} [B {...}] B (I) {...} B(I, I, I); B; -B { ... }; +B {...}; if (B) ... @@ -53,7 +53,7 @@ B is a small ISO-C++ style exception handling library for use in the ISO-C language. It allows you to use the paradigm of throwing and catching exceptions in order to reduce the amount of error handling -code in without making your program less robust. This is achieved +code without making your program less robust. This is achieved by directly transferring exceptional return codes (and the program control flow) from the location where it was raised (throw point) to the location where it is handled (catch point) - usually from a deeply @@ -133,22 +133,25 @@ =back -=item B { ... } B (I) { ... } +=item B {...} [B {...}] B (I) {...} This is the main construct provided by B. It is modeled after the ISO-C++ C-C construct which in turn is very similar to an ISO-C C-C construct. It consists of an B block which forms the dynamic scope of the exception handling (i.e. exceptions -thrown there are or from routines called from there are catched) and a +directly thrown there or thrown from subroutines are catched), an +optional B block for performing cleanup sequences and a B block where the caught exceptions are handled. -The B and B cannot be used seperately, they work only -in combination. In contrast to ISO-C++ there is only one B -block and not multiple ones (all B exceptions are of the -same ISO-C type B). If an exception is caught, it is stored in -I for inspection (or re-throwing) inside the B -block. Although declared outside, the I is only valid -within the B block. But it can be re-used in following +# CONTROL FLOW FIXME! + +The B, B and B cannot be used seperately, +they work only in combination. In contrast to ISO-C++ there is only +one B block and not multiple ones (all B exceptions +are of the same ISO-C type B). If an exception is caught, it +is stored in I for inspection (or re-throwing) inside the +B block. Although declared outside, the I is only +valid within the B block. But it can be re-used in following B/B constructs, of course. The B block is a regular ISO-C language block, but it is not @@ -182,7 +185,7 @@ I.ex_value) but with the difference that the C, C and C elements of the thrown exception are kept. -=item B { ... } +=item B {...} This directive executes its block while shielding against the throwing of exceptions, i.e., in the dynamic scope of B any @@ -232,7 +235,7 @@ This is called by the epilog of B to perform additional operations at the new (restored) machine context after an exception was -cought. Usually this is a no-operation macro. +caught. Usually this is a no-operation macro. =item B<__ex_mctx_restore>(I) Index: ossp-pkg/ex/ex_test.c RCS File: /v/ossp/cvs/ossp-pkg/ex/ex_test.c,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/ex/ex_test.c,v' 2>/dev/null --- ex_test.c 2002/01/26 22:45:37 1.6 +++ ex_test.c 2002/01/30 10:33:36 1.7 @@ -140,6 +140,35 @@ ts_test_fail(TS_CTX, "unexpected catching scope"); } +TS_TEST(test_cleanup) +{ + ex_t ex; + volatile int v1; + int cleanup; + + ts_test_check(TS_CTX, "cleanup handling"); + + v1 = 1234; + cleanup = 0; + ex_try { + v1 = 5678; + ex_throw(1, 2, 3); + } + ex_cleanup { + if (v1 != 5678) + ts_test_fail(TS_CTX, "v1 = %d (!= 5678)", v1); + cleanup = 1; + } + ex_catch (ex) { + if (v1 != 5678) + ts_test_fail(TS_CTX, "v1 = %d (!= 5678)", v1); + if (!(ex.ex_class == (void *)1 && ex.ex_object == (void *)2 && ex.ex_value == (void *)3)) + ts_test_fail(TS_CTX, "unexpected exception contents"); + } + if (!cleanup) + ts_test_fail(TS_CTX, "ex_cleanup not executed"); +} + int main(int argc, char *argv[]) { ts_suite_t *ts; @@ -150,6 +179,7 @@ ts_suite_test(ts, test_value, "exception value passing"); ts_suite_test(ts, test_variables, "variable value preservation"); ts_suite_test(ts, test_shield, "exception shielding"); + ts_suite_test(ts, test_cleanup, "cleanup handling"); n = ts_suite_run(ts); ts_suite_free(ts); return n;