summaryrefslogtreecommitdiff
path: root/fitz
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-12-03 14:11:49 +0000
committerRobin Watts <robin.watts@artifex.com>2012-12-03 16:28:52 +0000
commit95c84a2ec5bfb76c9b0aec03fdc68005800b4792 (patch)
tree2ef0428996626a10285e301391243078e52242d0 /fitz
parentf6b64c3e6e3c91f71c4febe35037a1cb57fe5461 (diff)
downloadmupdf-95c84a2ec5bfb76c9b0aec03fdc68005800b4792.tar.xz
Tweak fz_try/fz_always/fz_catch to handle throws from within always.
Throwing from within the always block is bad practice, but attempt to cope with it gracefully.
Diffstat (limited to 'fitz')
-rw-r--r--fitz/base_error.c33
-rw-r--r--fitz/fitz.h7
2 files changed, 36 insertions, 4 deletions
diff --git a/fitz/base_error.c b/fitz/base_error.c
index 995f59c6..869bf95e 100644
--- a/fitz/base_error.c
+++ b/fitz/base_error.c
@@ -43,10 +43,39 @@ void fz_warn(fz_context *ctx, char *fmt, ...)
/* Error context */
+/* When we first setjmp, code is set to 0. Whenever we throw, we add 2 to
+ * this code. Whenever we enter the always block, we add 1.
+ *
+ * fz_push_try sets code to 0.
+ * If (fz_throw called within fz_try)
+ * fz_throw makes code = 2.
+ * If (no always block present)
+ * enter catch region with code = 2. OK.
+ * else
+ * fz_always entered as code < 3; Makes code = 3;
+ * if (fz_throw called within fz_always)
+ * fz_throw makes code = 5
+ * fz_always is not reentered.
+ * catch region entered with code = 5. OK.
+ * else
+ * catch region entered with code = 3. OK
+ * else
+ * if (no always block present)
+ * catch region not entered as code = 0. OK.
+ * else
+ * fz_always entered as code < 3. makes code = 1
+ * if (fz_throw called within fz_always)
+ * fz_throw makes code = 3;
+ * fz_always NOT entered as code >= 3
+ * catch region entered with code = 3. OK.
+ * else
+ * catch region entered with code = 1.
+ */
+
static void throw(fz_error_context *ex)
{
if (ex->top >= 0) {
- fz_longjmp(ex->stack[ex->top].buffer, 1);
+ fz_longjmp(ex->stack[ex->top].buffer, ex->stack[ex->top].code + 2);
} else {
fprintf(stderr, "uncaught exception: %s\n", ex->message);
LOGE("uncaught exception: %s\n", ex->message);
@@ -60,7 +89,7 @@ int fz_push_try(fz_error_context *ex)
ex->top++;
/* Normal case, get out of here quick */
if (ex->top < nelem(ex->stack)-1)
- return 1;
+ return 1; /* We exit here, and the setjmp sets the code to 0 */
/* We reserve the top slot on the exception stack purely to cope with
* the case when we overflow. If we DO hit this, then we 'throw'
* immediately - returning 0 stops the setjmp happening and takes us
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 314fadd6..8f2a6edc 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -250,12 +250,15 @@ void fz_var_imp(void *);
#define fz_always(ctx) \
} while (0); \
} \
- { do { \
+ if (ctx->error->stack[ctx->error->top].code < 3) \
+ { \
+ ctx->error->stack[ctx->error->top].code++; \
+ do { \
#define fz_catch(ctx) \
} while(0); \
} \
- if (ctx->error->stack[ctx->error->top--].code)
+ if (ctx->error->stack[ctx->error->top--].code > 1)
int fz_push_try(fz_error_context *ex);
void fz_throw(fz_context *, char *, ...) __printflike(2, 3);