+ * 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)
+
+/*