X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=err.h;h=358cadfe942f4685d0166c8fa0bb5eb5641666fb;hp=2800526a93fdb8a98ff1ffbf6d68d1ba834eec5c;hb=031b620e1f3a16078da45ce00352508764902786;hpb=4535c379ced2bdb6a4b414f71080fa0c6f5180aa diff --git a/err.h b/err.h index 2800526..358cadf 100644 --- a/err.h +++ b/err.h @@ -13,10 +13,10 @@ */ /* - * functions for debug and error handling + * functions for debug and error handling, for internal use only */ -#ifdef DEBUG +#ifdef UCI_DEBUG #define DPRINTF(...) fprintf(stderr, __VA_ARGS__) #else #define DPRINTF(...) @@ -27,6 +27,7 @@ * in the context. */ #define UCI_THROW(ctx, err) do { \ + DPRINTF("Exception: %s in %s, %s:%d\n", #err, __func__, __FILE__, __LINE__); \ longjmp(ctx->trap, err); \ } while (0) @@ -36,13 +37,17 @@ * * NB: this does not handle recursion at all. Calling externally visible * functions from other uci functions is only allowed at the end of the - * calling function. + * calling function, or by wrapping the function call in UCI_TRAP_SAVE + * and UCI_TRAP_RESTORE. */ -#define UCI_HANDLE_ERR(ctx) do { \ - int __val; \ +#define UCI_HANDLE_ERR(ctx) do { \ + DPRINTF("ENTER: %s\n", __func__); \ + int __val = 0; \ if (!ctx) \ return UCI_ERR_INVAL; \ - __val = setjmp(ctx->trap); \ + if (!ctx->internal) \ + __val = setjmp(ctx->trap); \ + ctx->internal = false; \ if (__val) { \ ctx->errno = __val; \ return __val; \ @@ -50,6 +55,37 @@ } while (0) /* + * In a block enclosed by UCI_TRAP_SAVE and UCI_TRAP_RESTORE, all exceptions + * are intercepted and redirected to the label specified in 'handler' + * after UCI_TRAP_RESTORE, or when reaching the 'handler' label, the old + * exception handler is restored + */ +#define UCI_TRAP_SAVE(ctx, handler) do { \ + jmp_buf __old_trap; \ + int __val; \ + memcpy(__old_trap, ctx->trap, sizeof(ctx->trap)); \ + __val = setjmp(ctx->trap); \ + if (__val) { \ + ctx->errno = __val; \ + memcpy(ctx->trap, __old_trap, sizeof(ctx->trap)); \ + goto handler; \ + } +#define UCI_TRAP_RESTORE(ctx) \ + memcpy(ctx->trap, __old_trap, sizeof(ctx->trap)); \ +} while(0) + +/** + * UCI_INTERNAL: Do an internal call of a public API function + * + * Sets Exception handling to passthrough mode. + * Allows API functions to change behavior compared to public use + */ +#define UCI_INTERNAL(func, ctx, ...) do { \ + ctx->internal = true; \ + func(ctx, __VA_ARGS__); \ +} while (0) + +/* * check the specified condition. * throw an invalid argument exception if it's false */ @@ -60,4 +96,3 @@ } \ } while (0) -