base_error.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #include "fitz-internal.h"
  2. /* Warning context */
  3. void fz_var_imp(void *var)
  4. {
  5. UNUSED(var); /* Do nothing */
  6. }
  7. void fz_flush_warnings(fz_context *ctx)
  8. {
  9. if (ctx->warn->count > 1)
  10. {
  11. fprintf(stderr, "warning: ... repeated %d times ...\n", ctx->warn->count);
  12. LOGE("warning: ... repeated %d times ...\n", ctx->warn->count);
  13. }
  14. ctx->warn->message[0] = 0;
  15. ctx->warn->count = 0;
  16. }
  17. void fz_warn(fz_context *ctx, const char *fmt, ...)
  18. {
  19. va_list ap;
  20. char buf[sizeof ctx->warn->message];
  21. va_start(ap, fmt);
  22. vsnprintf(buf, sizeof buf, fmt, ap);
  23. va_end(ap);
  24. if (!strcmp(buf, ctx->warn->message))
  25. {
  26. ctx->warn->count++;
  27. }
  28. else
  29. {
  30. fz_flush_warnings(ctx);
  31. fprintf(stderr, "warning: %s\n", buf);
  32. LOGE("warning: %s\n", buf);
  33. fz_strlcpy(ctx->warn->message, buf, sizeof ctx->warn->message);
  34. ctx->warn->count = 1;
  35. }
  36. }
  37. /* Error context */
  38. /* When we first setjmp, code is set to 0. Whenever we throw, we add 2 to
  39. * this code. Whenever we enter the always block, we add 1.
  40. *
  41. * fz_push_try sets code to 0.
  42. * If (fz_throw called within fz_try)
  43. * fz_throw makes code = 2.
  44. * If (no always block present)
  45. * enter catch region with code = 2. OK.
  46. * else
  47. * fz_always entered as code < 3; Makes code = 3;
  48. * if (fz_throw called within fz_always)
  49. * fz_throw makes code = 5
  50. * fz_always is not reentered.
  51. * catch region entered with code = 5. OK.
  52. * else
  53. * catch region entered with code = 3. OK
  54. * else
  55. * if (no always block present)
  56. * catch region not entered as code = 0. OK.
  57. * else
  58. * fz_always entered as code < 3. makes code = 1
  59. * if (fz_throw called within fz_always)
  60. * fz_throw makes code = 3;
  61. * fz_always NOT entered as code >= 3
  62. * catch region entered with code = 3. OK.
  63. * else
  64. * catch region entered with code = 1.
  65. */
  66. static void throw(fz_error_context *ex)
  67. {
  68. if (ex->top >= 0) {
  69. fz_longjmp(ex->stack[ex->top].buffer, ex->stack[ex->top].code + 2);
  70. } else {
  71. fprintf(stderr, "uncaught exception: %s\n", ex->message);
  72. LOGE("uncaught exception: %s\n", ex->message);
  73. exit(EXIT_FAILURE);
  74. }
  75. }
  76. int fz_push_try(fz_error_context *ex)
  77. {
  78. assert(ex);
  79. ex->top++;
  80. /* Normal case, get out of here quick */
  81. if (ex->top < nelem(ex->stack)-1)
  82. return 1; /* We exit here, and the setjmp sets the code to 0 */
  83. /* We reserve the top slot on the exception stack purely to cope with
  84. * the case when we overflow. If we DO hit this, then we 'throw'
  85. * immediately - returning 0 stops the setjmp happening and takes us
  86. * direct to the always/catch clauses. */
  87. assert(ex->top == nelem(ex->stack)-1);
  88. strcpy(ex->message, "exception stack overflow!");
  89. ex->stack[ex->top].code = 2;
  90. fprintf(stderr, "error: %s\n", ex->message);
  91. LOGE("error: %s\n", ex->message);
  92. return 0;
  93. }
  94. const char *fz_caught(fz_context *ctx)
  95. {
  96. assert(ctx);
  97. assert(ctx->error);
  98. return ctx->error->message;
  99. }
  100. void fz_throw(fz_context *ctx, const char *fmt, ...)
  101. {
  102. va_list args;
  103. va_start(args, fmt);
  104. vsnprintf(ctx->error->message, sizeof ctx->error->message, fmt, args);
  105. va_end(args);
  106. fz_flush_warnings(ctx);
  107. fprintf(stderr, "error: %s\n", ctx->error->message);
  108. LOGE("error: %s\n", ctx->error->message);
  109. throw(ctx->error);
  110. }
  111. void fz_rethrow(fz_context *ctx)
  112. {
  113. throw(ctx->error);
  114. }