Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/fitz/error.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 // Copyright (C) 2004-2024 Artifex Software, Inc. | |
| 2 // | |
| 3 // This file is part of MuPDF. | |
| 4 // | |
| 5 // MuPDF is free software: you can redistribute it and/or modify it under the | |
| 6 // terms of the GNU Affero General Public License as published by the Free | |
| 7 // Software Foundation, either version 3 of the License, or (at your option) | |
| 8 // any later version. | |
| 9 // | |
| 10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | |
| 13 // details. | |
| 14 // | |
| 15 // You should have received a copy of the GNU Affero General Public License | |
| 16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> | |
| 17 // | |
| 18 // Alternative licensing terms are available from the licensor. | |
| 19 // For commercial licensing, see <https://www.artifex.com/> or contact | |
| 20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, | |
| 21 // CA 94129, USA, for further information. | |
| 22 | |
| 23 #include "mupdf/fitz.h" | |
| 24 | |
| 25 #include <assert.h> | |
| 26 #include <stdarg.h> | |
| 27 #include <stdio.h> | |
| 28 #include <stdlib.h> | |
| 29 #include <string.h> | |
| 30 #include <errno.h> | |
| 31 | |
| 32 #ifdef _WIN32 | |
| 33 #ifndef NDEBUG | |
| 34 #define USE_OUTPUT_DEBUG_STRING | |
| 35 #include <windows.h> | |
| 36 #endif | |
| 37 #endif | |
| 38 | |
| 39 #ifdef __ANDROID__ | |
| 40 #define USE_ANDROID_LOG | |
| 41 #include <android/log.h> | |
| 42 #endif | |
| 43 | |
| 44 void fz_default_error_callback(void *user, const char *message) | |
| 45 { | |
| 46 /* TODO: send errcode and format it here instead of in fz_report_error */ | |
| 47 fputs(message, stderr); | |
| 48 fputc('\n', stderr); | |
| 49 #ifdef USE_OUTPUT_DEBUG_STRING | |
| 50 OutputDebugStringA(message); | |
| 51 OutputDebugStringA("\n"); | |
| 52 #endif | |
| 53 #ifdef USE_ANDROID_LOG | |
| 54 __android_log_print(ANDROID_LOG_ERROR, "libmupdf", "%s", message); | |
| 55 #endif | |
| 56 } | |
| 57 | |
| 58 void fz_default_warning_callback(void *user, const char *message) | |
| 59 { | |
| 60 fprintf(stderr, "warning: %s\n", message); | |
| 61 #ifdef USE_OUTPUT_DEBUG_STRING | |
| 62 OutputDebugStringA("warning: "); | |
| 63 OutputDebugStringA(message); | |
| 64 OutputDebugStringA("\n"); | |
| 65 #endif | |
| 66 #ifdef USE_ANDROID_LOG | |
| 67 __android_log_print(ANDROID_LOG_WARN, "libmupdf", "%s", message); | |
| 68 #endif | |
| 69 } | |
| 70 | |
| 71 /* Warning context */ | |
| 72 | |
| 73 void fz_set_warning_callback(fz_context *ctx, fz_warning_cb *warning_cb, void *user) | |
| 74 { | |
| 75 ctx->warn.print_user = user; | |
| 76 ctx->warn.print = warning_cb; | |
| 77 } | |
| 78 | |
| 79 fz_warning_cb *fz_warning_callback(fz_context *ctx, void **user) | |
| 80 { | |
| 81 if (user) | |
| 82 *user = ctx->warn.print_user; | |
| 83 return ctx->warn.print; | |
| 84 } | |
| 85 | |
| 86 void fz_var_imp(void *var) | |
| 87 { | |
| 88 /* Do nothing */ | |
| 89 } | |
| 90 | |
| 91 void fz_flush_warnings(fz_context *ctx) | |
| 92 { | |
| 93 if (ctx->warn.count > 1) | |
| 94 { | |
| 95 char buf[50]; | |
| 96 fz_snprintf(buf, sizeof buf, "... repeated %d times...", ctx->warn.count); | |
| 97 if (ctx->warn.print) | |
| 98 ctx->warn.print(ctx->warn.print_user, buf); | |
| 99 } | |
| 100 ctx->warn.message[0] = 0; | |
| 101 ctx->warn.count = 0; | |
| 102 } | |
| 103 | |
| 104 void (fz_vwarn)(fz_context *ctx, const char *fmt, va_list ap) | |
| 105 { | |
| 106 char buf[sizeof ctx->warn.message]; | |
| 107 | |
| 108 fz_vsnprintf(buf, sizeof buf, fmt, ap); | |
| 109 buf[sizeof(buf) - 1] = 0; | |
| 110 | |
| 111 if (!strcmp(buf, ctx->warn.message)) | |
| 112 { | |
| 113 ctx->warn.count++; | |
| 114 } | |
| 115 else | |
| 116 { | |
| 117 fz_flush_warnings(ctx); | |
| 118 if (ctx->warn.print) | |
| 119 ctx->warn.print(ctx->warn.print_user, buf); | |
| 120 fz_strlcpy(ctx->warn.message, buf, sizeof ctx->warn.message); | |
| 121 ctx->warn.count = 1; | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 void (fz_warn)(fz_context *ctx, const char *fmt, ...) | |
| 126 { | |
| 127 va_list ap; | |
| 128 va_start(ap, fmt); | |
| 129 fz_vwarn(ctx, fmt, ap); | |
| 130 va_end(ap); | |
| 131 } | |
| 132 | |
| 133 #if FZ_VERBOSE_EXCEPTIONS | |
| 134 void fz_vwarnFL(fz_context *ctx, const char *file, int line, const char *fmt, va_list ap) | |
| 135 { | |
| 136 char buf[sizeof ctx->warn.message]; | |
| 137 | |
| 138 fz_vsnprintf(buf, sizeof buf, fmt, ap); | |
| 139 buf[sizeof(buf) - 1] = 0; | |
| 140 | |
| 141 if (!strcmp(buf, ctx->warn.message)) | |
| 142 { | |
| 143 ctx->warn.count++; | |
| 144 } | |
| 145 else | |
| 146 { | |
| 147 fz_flush_warnings(ctx); | |
| 148 if (ctx->warn.print) | |
| 149 ctx->warn.print(ctx->warn.print_user, buf); | |
| 150 fz_strlcpy(ctx->warn.message, buf, sizeof ctx->warn.message); | |
| 151 ctx->warn.count = 1; | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 void fz_warnFL(fz_context *ctx, const char *file, int line, const char *fmt, ...) | |
| 156 { | |
| 157 va_list ap; | |
| 158 va_start(ap, fmt); | |
| 159 fz_vwarnFL(ctx, file, line, fmt, ap); | |
| 160 va_end(ap); | |
| 161 } | |
| 162 #endif | |
| 163 | |
| 164 /* Error context */ | |
| 165 | |
| 166 void fz_set_error_callback(fz_context *ctx, fz_error_cb *error_cb, void *user) | |
| 167 { | |
| 168 ctx->error.print_user = user; | |
| 169 ctx->error.print = error_cb; | |
| 170 } | |
| 171 | |
| 172 fz_error_cb *fz_error_callback(fz_context *ctx, void **user) | |
| 173 { | |
| 174 if (user) | |
| 175 *user = ctx->error.print_user; | |
| 176 return ctx->error.print; | |
| 177 } | |
| 178 | |
| 179 /* When we first setjmp, state is set to 0. Whenever we throw, we add 2 to | |
| 180 * this state. Whenever we enter the always block, we add 1. | |
| 181 * | |
| 182 * fz_push_try sets state to 0. | |
| 183 * If (fz_throw called within fz_try) | |
| 184 * fz_throw makes state = 2. | |
| 185 * If (no always block present) | |
| 186 * enter catch region with state = 2. OK. | |
| 187 * else | |
| 188 * fz_always entered as state < 3; Makes state = 3; | |
| 189 * if (fz_throw called within fz_always) | |
| 190 * fz_throw makes state = 5 | |
| 191 * fz_always is not reentered. | |
| 192 * catch region entered with state = 5. OK. | |
| 193 * else | |
| 194 * catch region entered with state = 3. OK | |
| 195 * else | |
| 196 * if (no always block present) | |
| 197 * catch region not entered as state = 0. OK. | |
| 198 * else | |
| 199 * fz_always entered as state < 3. makes state = 1 | |
| 200 * if (fz_throw called within fz_always) | |
| 201 * fz_throw makes state = 3; | |
| 202 * fz_always NOT entered as state >= 3 | |
| 203 * catch region entered with state = 3. OK. | |
| 204 * else | |
| 205 * catch region entered with state = 1. | |
| 206 */ | |
| 207 | |
| 208 FZ_NORETURN static void throw(fz_context *ctx, int code) | |
| 209 { | |
| 210 if (ctx->error.top > ctx->error.stack_base) | |
| 211 { | |
| 212 ctx->error.top->state += 2; | |
| 213 if (ctx->error.top->code != FZ_ERROR_NONE) | |
| 214 fz_warn(ctx, "clobbering previous error code and message (throw in always block?)"); | |
| 215 ctx->error.top->code = code; | |
| 216 fz_longjmp(ctx->error.top->buffer, 1); | |
| 217 } | |
| 218 else | |
| 219 { | |
| 220 fz_flush_warnings(ctx); | |
| 221 if (ctx->error.print) | |
| 222 ctx->error.print(ctx->error.print_user, "aborting process from uncaught error!"); | |
| 223 exit(EXIT_FAILURE); | |
| 224 } | |
| 225 } | |
| 226 | |
| 227 fz_jmp_buf *fz_push_try(fz_context *ctx) | |
| 228 { | |
| 229 /* If we would overflow the exception stack, throw an exception instead | |
| 230 * of entering the try block. We assume that we always have room for | |
| 231 * 1 extra level on the stack here - i.e. we throw the error on us | |
| 232 * starting to use the last level. */ | |
| 233 if (ctx->error.top + 2 >= ctx->error.stack_base + nelem(ctx->error.stack)) | |
| 234 { | |
| 235 fz_strlcpy(ctx->error.message, "exception stack overflow!", sizeof ctx->error.message); | |
| 236 | |
| 237 fz_flush_warnings(ctx); | |
| 238 if (ctx->error.print) | |
| 239 ctx->error.print(ctx->error.print_user, ctx->error.message); | |
| 240 | |
| 241 /* We need to arrive in the always/catch block as if throw had taken place. */ | |
| 242 ctx->error.top++; | |
| 243 ctx->error.top->state = 2; | |
| 244 ctx->error.top->code = FZ_ERROR_LIMIT; | |
| 245 } | |
| 246 else | |
| 247 { | |
| 248 ctx->error.top++; | |
| 249 ctx->error.top->state = 0; | |
| 250 ctx->error.top->code = FZ_ERROR_NONE; | |
| 251 } | |
| 252 return &ctx->error.top->buffer; | |
| 253 } | |
| 254 | |
| 255 int fz_do_try(fz_context *ctx) | |
| 256 { | |
| 257 #ifdef __COVERITY__ | |
| 258 return 1; | |
| 259 #else | |
| 260 return ctx->error.top->state == 0; | |
| 261 #endif | |
| 262 } | |
| 263 | |
| 264 int fz_do_always(fz_context *ctx) | |
| 265 { | |
| 266 #ifdef __COVERITY__ | |
| 267 return 1; | |
| 268 #else | |
| 269 if (ctx->error.top->state < 3) | |
| 270 { | |
| 271 ctx->error.top->state++; | |
| 272 return 1; | |
| 273 } | |
| 274 return 0; | |
| 275 #endif | |
| 276 } | |
| 277 | |
| 278 int (fz_do_catch)(fz_context *ctx) | |
| 279 { | |
| 280 ctx->error.errcode = ctx->error.top->code; | |
| 281 return (ctx->error.top--)->state > 1; | |
| 282 } | |
| 283 | |
| 284 int fz_caught(fz_context *ctx) | |
| 285 { | |
| 286 assert(ctx && ctx->error.errcode >= FZ_ERROR_NONE); | |
| 287 return ctx->error.errcode; | |
| 288 } | |
| 289 | |
| 290 int fz_caught_errno(fz_context *ctx) | |
| 291 { | |
| 292 assert(ctx && ctx->error.errcode == FZ_ERROR_SYSTEM); | |
| 293 return ctx->error.errnum; | |
| 294 } | |
| 295 | |
| 296 const char *fz_caught_message(fz_context *ctx) | |
| 297 { | |
| 298 assert(ctx && ctx->error.errcode >= FZ_ERROR_NONE); | |
| 299 return ctx->error.message; | |
| 300 } | |
| 301 | |
| 302 void (fz_log_error_printf)(fz_context *ctx, const char *fmt, ...) | |
| 303 { | |
| 304 va_list ap; | |
| 305 | |
| 306 va_start(ap, fmt); | |
| 307 (fz_vlog_error_printf)(ctx, fmt, ap); | |
| 308 va_end(ap); | |
| 309 } | |
| 310 | |
| 311 void (fz_vlog_error_printf)(fz_context *ctx, const char *fmt, va_list ap) | |
| 312 { | |
| 313 char message[256]; | |
| 314 | |
| 315 fz_flush_warnings(ctx); | |
| 316 if (ctx->error.print) | |
| 317 { | |
| 318 fz_vsnprintf(message, sizeof message, fmt, ap); | |
| 319 message[sizeof(message) - 1] = 0; | |
| 320 | |
| 321 ctx->error.print(ctx->error.print_user, message); | |
| 322 } | |
| 323 } | |
| 324 | |
| 325 void (fz_log_error)(fz_context *ctx, const char *str) | |
| 326 { | |
| 327 fz_flush_warnings(ctx); | |
| 328 if (ctx->error.print) | |
| 329 ctx->error.print(ctx->error.print_user, str); | |
| 330 } | |
| 331 | |
| 332 /* coverity[+kill] */ | |
| 333 FZ_NORETURN void (fz_vthrow)(fz_context *ctx, int code, const char *fmt, va_list ap) | |
| 334 { | |
| 335 if (ctx->error.errcode) | |
| 336 { | |
| 337 fz_flush_warnings(ctx); | |
| 338 fz_warn(ctx, "UNHANDLED EXCEPTION!"); | |
| 339 fz_report_error(ctx); | |
| 340 #ifdef CLUSTER | |
| 341 abort(); | |
| 342 #endif | |
| 343 } | |
| 344 | |
| 345 if (code == FZ_ERROR_SYSTEM) | |
| 346 ctx->error.errnum = errno; | |
| 347 else | |
| 348 ctx->error.errnum = 0; | |
| 349 | |
| 350 fz_vsnprintf(ctx->error.message, sizeof ctx->error.message, fmt, ap); | |
| 351 ctx->error.message[sizeof(ctx->error.message) - 1] = 0; | |
| 352 | |
| 353 throw(ctx, code); | |
| 354 } | |
| 355 | |
| 356 /* coverity[+kill] */ | |
| 357 FZ_NORETURN void (fz_throw)(fz_context *ctx, int code, const char *fmt, ...) | |
| 358 { | |
| 359 va_list ap; | |
| 360 va_start(ap, fmt); | |
| 361 fz_vthrow(ctx, code, fmt, ap); | |
| 362 va_end(ap); | |
| 363 } | |
| 364 | |
| 365 /* coverity[+kill] */ | |
| 366 FZ_NORETURN void (fz_rethrow)(fz_context *ctx) | |
| 367 { | |
| 368 assert(ctx && ctx->error.errcode >= FZ_ERROR_NONE); | |
| 369 throw(ctx, ctx->error.errcode); | |
| 370 } | |
| 371 | |
| 372 void (fz_morph_error)(fz_context *ctx, int fromerr, int toerr) | |
| 373 { | |
| 374 assert(ctx && ctx->error.errcode >= FZ_ERROR_NONE); | |
| 375 if (ctx->error.errcode == fromerr) | |
| 376 ctx->error.errcode = toerr; | |
| 377 } | |
| 378 | |
| 379 void (fz_rethrow_if)(fz_context *ctx, int err) | |
| 380 { | |
| 381 assert(ctx && ctx->error.errcode >= FZ_ERROR_NONE); | |
| 382 if (ctx->error.errcode == err) | |
| 383 fz_rethrow(ctx); | |
| 384 } | |
| 385 | |
| 386 void (fz_rethrow_unless)(fz_context *ctx, int err) | |
| 387 { | |
| 388 assert(ctx && ctx->error.errcode >= FZ_ERROR_NONE); | |
| 389 if (ctx->error.errcode != err) | |
| 390 fz_rethrow(ctx); | |
| 391 } | |
| 392 | |
| 393 static const char * | |
| 394 fz_error_type_name(enum fz_error_type exc) | |
| 395 { | |
| 396 switch (exc) | |
| 397 { | |
| 398 case FZ_ERROR_NONE: return "none"; | |
| 399 case FZ_ERROR_GENERIC: return "generic"; | |
| 400 case FZ_ERROR_SYSTEM: return "system"; | |
| 401 case FZ_ERROR_LIBRARY: return "library"; | |
| 402 case FZ_ERROR_UNSUPPORTED: return "unsupported"; | |
| 403 case FZ_ERROR_ARGUMENT: return "argument"; | |
| 404 case FZ_ERROR_LIMIT: return "limit"; | |
| 405 case FZ_ERROR_FORMAT: return "format"; | |
| 406 case FZ_ERROR_SYNTAX: return "syntax"; | |
| 407 case FZ_ERROR_TRYLATER: return "trylater"; | |
| 408 case FZ_ERROR_ABORT: return "abort"; | |
| 409 case FZ_ERROR_REPAIRED: return "repaired"; | |
| 410 } | |
| 411 return "invalid error type"; | |
| 412 } | |
| 413 | |
| 414 #if FZ_VERBOSE_EXCEPTIONS | |
| 415 | |
| 416 int fz_do_catchFL(fz_context *ctx, const char *file, int line) | |
| 417 { | |
| 418 int rc = (fz_do_catch)(ctx); | |
| 419 if (rc) | |
| 420 (fz_log_error_printf)(ctx, "%s:%d: Catching", file, line); | |
| 421 return rc; | |
| 422 } | |
| 423 | |
| 424 | |
| 425 void fz_log_error_printfFL(fz_context *ctx, const char *file, int line, const char *fmt, ...) | |
| 426 { | |
| 427 va_list ap; | |
| 428 | |
| 429 va_start(ap, fmt); | |
| 430 fz_vlog_error_printfFL(ctx, file, line, fmt, ap); | |
| 431 va_end(ap); | |
| 432 } | |
| 433 | |
| 434 void fz_vlog_error_printfFL(fz_context *ctx, const char *file, int line, const char *fmt, va_list ap) | |
| 435 { | |
| 436 char message[256]; | |
| 437 | |
| 438 fz_flush_warnings(ctx); | |
| 439 if (ctx->error.print) | |
| 440 { | |
| 441 fz_vsnprintf(message, sizeof message, fmt, ap); | |
| 442 message[sizeof(message) - 1] = 0; | |
| 443 | |
| 444 fz_log_errorFL(ctx, file, line, message); | |
| 445 } | |
| 446 } | |
| 447 | |
| 448 void fz_log_errorFL(fz_context *ctx, const char *file, int line, const char *str) | |
| 449 { | |
| 450 char message[256]; | |
| 451 | |
| 452 fz_flush_warnings(ctx); | |
| 453 if (ctx->error.print) | |
| 454 { | |
| 455 fz_snprintf(message, sizeof message, "%s:%d '%s'", file, line, str); | |
| 456 message[sizeof(message) - 1] = 0; | |
| 457 ctx->error.print(ctx->error.print_user, message); | |
| 458 } | |
| 459 } | |
| 460 | |
| 461 /* coverity[+kill] */ | |
| 462 FZ_NORETURN void fz_vthrowFL(fz_context *ctx, const char *file, int line, int code, const char *fmt, va_list ap) | |
| 463 { | |
| 464 if (ctx->error.errcode) | |
| 465 { | |
| 466 fz_flush_warnings(ctx); | |
| 467 fz_warn(ctx, "UNHANDLED EXCEPTION!"); | |
| 468 fz_report_error(ctx); | |
| 469 #ifdef CLUSTER | |
| 470 abort(); | |
| 471 #endif | |
| 472 } | |
| 473 | |
| 474 fz_vsnprintf(ctx->error.message, sizeof ctx->error.message, fmt, ap); | |
| 475 ctx->error.message[sizeof(ctx->error.message) - 1] = 0; | |
| 476 | |
| 477 (fz_log_error_printf)(ctx, "%s:%d: Throwing %s '%s'", file, line, fz_error_type_name(code), ctx->error.message); | |
| 478 | |
| 479 throw(ctx, code); | |
| 480 } | |
| 481 | |
| 482 /* coverity[+kill] */ | |
| 483 FZ_NORETURN void fz_throwFL(fz_context *ctx, const char *file, int line, int code, const char *fmt, ...) | |
| 484 { | |
| 485 va_list ap; | |
| 486 va_start(ap, fmt); | |
| 487 fz_vthrowFL(ctx, file, line, code, fmt, ap); | |
| 488 va_end(ap); | |
| 489 } | |
| 490 | |
| 491 /* coverity[+kill] */ | |
| 492 FZ_NORETURN void fz_rethrowFL(fz_context *ctx, const char *file, int line) | |
| 493 { | |
| 494 assert(ctx && ctx->error.errcode >= FZ_ERROR_NONE); | |
| 495 (fz_log_error_printf)(ctx, "%s:%d: Rethrowing", file, line); | |
| 496 throw(ctx, ctx->error.errcode); | |
| 497 } | |
| 498 | |
| 499 void fz_morph_errorFL(fz_context *ctx, const char *file, int line, int fromerr, int toerr) | |
| 500 { | |
| 501 assert(ctx && ctx->error.errcode >= FZ_ERROR_NONE); | |
| 502 if (ctx->error.errcode == fromerr) | |
| 503 { | |
| 504 (fz_log_error_printf)(ctx, "%s:%d: Morphing %s->%s", file, line, fz_error_type_name(fromerr), fz_error_type_name(toerr)); | |
| 505 ctx->error.errcode = toerr; | |
| 506 } | |
| 507 } | |
| 508 | |
| 509 void fz_rethrow_unlessFL(fz_context *ctx, const char *file, int line, int err) | |
| 510 { | |
| 511 assert(ctx && ctx->error.errcode >= FZ_ERROR_NONE); | |
| 512 if (ctx->error.errcode != err) | |
| 513 { | |
| 514 (fz_log_error_printf)(ctx, "%s:%d: Rethrowing", file, line); | |
| 515 (fz_rethrow)(ctx); | |
| 516 } | |
| 517 } | |
| 518 | |
| 519 void fz_rethrow_ifFL(fz_context *ctx, const char *file, int line, int err) | |
| 520 { | |
| 521 assert(ctx && ctx->error.errcode >= FZ_ERROR_NONE); | |
| 522 if (ctx->error.errcode == err) | |
| 523 { | |
| 524 (fz_log_error_printf)(ctx, "%s:%d: Rethrowing", file, line); | |
| 525 (fz_rethrow)(ctx); | |
| 526 } | |
| 527 } | |
| 528 #endif | |
| 529 | |
| 530 void fz_start_throw_on_repair(fz_context *ctx) | |
| 531 { | |
| 532 fz_lock(ctx, FZ_LOCK_ALLOC); | |
| 533 ctx->throw_on_repair++; | |
| 534 fz_unlock(ctx, FZ_LOCK_ALLOC); | |
| 535 } | |
| 536 | |
| 537 void fz_end_throw_on_repair(fz_context *ctx) | |
| 538 { | |
| 539 fz_lock(ctx, FZ_LOCK_ALLOC); | |
| 540 ctx->throw_on_repair--; | |
| 541 fz_unlock(ctx, FZ_LOCK_ALLOC); | |
| 542 } | |
| 543 | |
| 544 void fz_report_error(fz_context *ctx) | |
| 545 { | |
| 546 #ifdef CLUSTER | |
| 547 if (ctx->error.errcode == FZ_ERROR_TRYLATER || ctx->error.errcode == FZ_ERROR_ABORT) | |
| 548 { | |
| 549 fprintf(stderr, "REPORTED ERROR THAT IS TRYLATER OR ABORT\n"); | |
| 550 abort(); | |
| 551 } | |
| 552 #endif | |
| 553 /* TODO: send errcode to fz_log_error instead of formatting it here */ | |
| 554 fz_log_error_printf(ctx, "%s error: %s", fz_error_type_name(ctx->error.errcode), ctx->error.message); | |
| 555 ctx->error.errcode = FZ_ERROR_NONE; | |
| 556 } | |
| 557 | |
| 558 void fz_ignore_error(fz_context *ctx) | |
| 559 { | |
| 560 #ifdef CLUSTER | |
| 561 if (ctx->error.errcode != FZ_ERROR_TRYLATER && ctx->error.errcode != FZ_ERROR_ABORT) | |
| 562 { | |
| 563 fprintf(stderr, "IGNORED ERROR THAT IS NOT TRYLATER OR ABORT\n"); | |
| 564 abort(); | |
| 565 } | |
| 566 #endif | |
| 567 ctx->error.errcode = FZ_ERROR_NONE; | |
| 568 } | |
| 569 | |
| 570 /* Convert an error into another runtime exception. */ | |
| 571 const char *fz_convert_error(fz_context *ctx, int *code) | |
| 572 { | |
| 573 if (code) | |
| 574 *code = ctx->error.errcode; | |
| 575 ctx->error.errcode = FZ_ERROR_NONE; | |
| 576 return ctx->error.message; | |
| 577 } |
