diff options
Diffstat (limited to 'source/fitz/error.c')
-rw-r--r-- | source/fitz/error.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/source/fitz/error.c b/source/fitz/error.c new file mode 100644 index 00000000..50b3c5aa --- /dev/null +++ b/source/fitz/error.c @@ -0,0 +1,155 @@ +#include "mupdf/fitz.h" + +/* Warning context */ + +void fz_var_imp(void *var) +{ + UNUSED(var); /* Do nothing */ +} + +void fz_flush_warnings(fz_context *ctx) +{ + if (ctx->warn->count > 1) + { + fprintf(stderr, "warning: ... repeated %d times ...\n", ctx->warn->count); + LOGE("warning: ... repeated %d times ...\n", ctx->warn->count); + } + ctx->warn->message[0] = 0; + ctx->warn->count = 0; +} + +void fz_warn(fz_context *ctx, const char *fmt, ...) +{ + va_list ap; + char buf[sizeof ctx->warn->message]; + + va_start(ap, fmt); + vsnprintf(buf, sizeof buf, fmt, ap); + va_end(ap); + + if (!strcmp(buf, ctx->warn->message)) + { + ctx->warn->count++; + } + else + { + fz_flush_warnings(ctx); + fprintf(stderr, "warning: %s\n", buf); + LOGE("warning: %s\n", buf); + fz_strlcpy(ctx->warn->message, buf, sizeof ctx->warn->message); + ctx->warn->count = 1; + } +} + +/* 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) FZ_NORETURN; + +static void throw(fz_error_context *ex) +{ + if (ex->top >= 0) { + 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); + exit(EXIT_FAILURE); + } +} + +int fz_push_try(fz_error_context *ex) +{ + assert(ex); + ex->top++; + /* Normal case, get out of here quick */ + if (ex->top < nelem(ex->stack)-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 + * direct to the always/catch clauses. */ + assert(ex->top == nelem(ex->stack)-1); + strcpy(ex->message, "exception stack overflow!"); + ex->stack[ex->top].code = 2; + fprintf(stderr, "error: %s\n", ex->message); + LOGE("error: %s\n", ex->message); + return 0; +} + +int fz_caught(fz_context *ctx) +{ + assert(ctx && ctx->error && ctx->error->errcode >= FZ_ERROR_NONE); + return ctx->error->errcode; +} + +const char *fz_caught_message(fz_context *ctx) +{ + assert(ctx && ctx->error && ctx->error->errcode >= FZ_ERROR_NONE); + return ctx->error->message; +} + +void fz_throw(fz_context *ctx, int code, const char *fmt, ...) +{ + va_list args; + ctx->error->errcode = code; + va_start(args, fmt); + vsnprintf(ctx->error->message, sizeof ctx->error->message, fmt, args); + va_end(args); + + fz_flush_warnings(ctx); + fprintf(stderr, "error: %s\n", ctx->error->message); + LOGE("error: %s\n", ctx->error->message); + + throw(ctx->error); +} + +void fz_rethrow(fz_context *ctx) +{ + assert(ctx && ctx->error && ctx->error->errcode >= FZ_ERROR_NONE); + throw(ctx->error); +} + +void fz_rethrow_message(fz_context *ctx, const char *fmt, ...) +{ + va_list args; + + assert(ctx && ctx->error && ctx->error->errcode >= FZ_ERROR_NONE); + + va_start(args, fmt); + vsnprintf(ctx->error->message, sizeof ctx->error->message, fmt, args); + va_end(args); + + fz_flush_warnings(ctx); + fprintf(stderr, "error: %s\n", ctx->error->message); + LOGE("error: %s\n", ctx->error->message); + + throw(ctx->error); +} |