summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2017-09-06 17:03:04 +0200
committerTor Andersson <tor.andersson@artifex.com>2018-10-26 15:29:11 +0200
commitb3ceba9fa1d19c1004aec38b0a8870154a865ea4 (patch)
treebc94d586b4fc6af72ba347ebf1d8ef5c4fd74c61
parent4f8796cafcd5c15247fb85e7febd1bb591d0a853 (diff)
downloadmupdf-b3ceba9fa1d19c1004aec38b0a8870154a865ea4.tar.xz
Rewrite try/always/catch macros to allow fz_context to be opaque.
Hide fz_stack_slot and exception handling details too. Also make sure we have an initialized jmp_buf so we can safely throw from the always block even in the exception stack overflow case.
-rw-r--r--include/mupdf/fitz/context.h28
-rw-r--r--source/fitz/error.c60
2 files changed, 43 insertions, 45 deletions
diff --git a/include/mupdf/fitz/context.h b/include/mupdf/fitz/context.h
index 8f72ad99..de83d0e6 100644
--- a/include/mupdf/fitz/context.h
+++ b/include/mupdf/fitz/context.h
@@ -57,25 +57,15 @@ void fz_var_imp(void *);
attention to the man behind the curtain.
*/
-#define fz_try(ctx) \
- { \
- if (fz_push_try(ctx)) { \
- if (fz_setjmp((ctx)->error->top->buffer) == 0) do \
-
-#define fz_always(ctx) \
- while (0); \
- } \
- if (ctx->error->top->code < 3) { \
- ctx->error->top->code++; \
- do \
-
-#define fz_catch(ctx) \
- while (0); \
- } \
- } \
- if ((ctx->error->top--)->code > 1)
-
-int fz_push_try(fz_context *ctx);
+void *fz_push_try(fz_context *ctx);
+int fz_do_try(fz_context *ctx);
+int fz_do_always(fz_context *ctx);
+int fz_do_catch(fz_context *ctx);
+
+#define fz_try(ctx) if (!fz_setjmp(fz_push_try(ctx))) if (fz_do_try(ctx)) do
+#define fz_always(ctx) while (0); if (fz_do_always(ctx)) do
+#define fz_catch(ctx) while (0); if (fz_do_catch(ctx))
+
FZ_NORETURN void fz_vthrow(fz_context *ctx, int errcode, const char *, va_list ap);
FZ_NORETURN void fz_throw(fz_context *ctx, int errcode, const char *, ...) FZ_PRINTFLIKE(3,4);
FZ_NORETURN void fz_rethrow(fz_context *ctx);
diff --git a/source/fitz/error.c b/source/fitz/error.c
index fe1045dd..8f4d6f50 100644
--- a/source/fitz/error.c
+++ b/source/fitz/error.c
@@ -123,19 +123,17 @@ FZ_NORETURN static void throw(fz_context *ctx)
}
}
-/* Only called when we hit the bottom of the exception stack.
- * Do the same as fz_throw, but don't actually throw. */
-static int fz_fake_throw(fz_context *ctx, int code, const char *fmt, ...)
+void *fz_push_try(fz_context *ctx)
{
- va_list args;
- ctx->error->errcode = code;
- va_start(args, fmt);
- fz_vsnprintf(ctx->error->message, sizeof ctx->error->message, fmt, args);
- ctx->error->message[sizeof(ctx->error->message) - 1] = 0;
- va_end(args);
-
- if (code != FZ_ERROR_ABORT)
+ /* If we would overflow the exception stack, throw an exception instead
+ * of entering the try block. We assume that we always have room for
+ * 1 extra level on the stack here - i.e. we throw the error on us
+ * starting to use the last level. */
+ if (ctx->error->top + 2 >= ctx->error->stack + nelem(ctx->error->stack))
{
+ ctx->error->errcode = FZ_ERROR_GENERIC;
+ fz_strlcpy(ctx->error->message, "exception stack overflow!", sizeof ctx->error->message);
+
fz_flush_warnings(ctx);
fprintf(stderr, "error: %s\n", ctx->error->message);
#ifdef USE_OUTPUT_DEBUG_STRING
@@ -146,27 +144,37 @@ static int fz_fake_throw(fz_context *ctx, int code, const char *fmt, ...)
#ifdef USE_ANDROID_LOG
__android_log_print(ANDROID_LOG_ERROR, "libmupdf", "%s", ctx->error->message);
#endif
+
+ /* We need to arrive in the always/catch block as if throw had taken place. */
+ ctx->error->top++;
+ ctx->error->top->code = 2;
+ }
+ else
+ {
+ ctx->error->top++;
+ ctx->error->top->code = 0;
}
+ return ctx->error->top->buffer;
+}
- /* We need to arrive in the always/catch block as if throw
- * had taken place. */
- ctx->error->top++;
- ctx->error->top->code = 2;
- return 0;
+int fz_do_try(fz_context *ctx)
+{
+ return ctx->error->top->code == 0;
}
-int fz_push_try(fz_context *ctx)
+int fz_do_always(fz_context *ctx)
{
- /* If we would overflow the exception stack, throw an exception instead
- * of entering the try block. We assume that we always have room for
- * 1 extra level on the stack here - i.e. we throw the error on us
- * starting to use the last level. */
- if (ctx->error->top + 2 >= ctx->error->stack + nelem(ctx->error->stack))
- return fz_fake_throw(ctx, FZ_ERROR_GENERIC, "exception stack overflow!");
+ if (ctx->error->top->code < 3)
+ {
+ ctx->error->top->code++;
+ return 1;
+ }
+ return 0;
+}
- ctx->error->top++;
- ctx->error->top->code = 0;
- return 1;
+int fz_do_catch(fz_context *ctx)
+{
+ return (ctx->error->top--)->code > 1;
}
int fz_caught(fz_context *ctx)