more error handling for internal uci_import calls
[project/uci.git] / err.h
diff --git a/err.h b/err.h
index 469164c..358cadf 100644 (file)
--- a/err.h
+++ b/err.h
@@ -16,7 +16,7 @@
  * 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)
 
  *
  * 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;           \
 } 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
  */