]> git.imager.perl.org - imager.git/blobdiff - error.c
use non-deprecated encoding ids for freetype 2
[imager.git] / error.c
diff --git a/error.c b/error.c
index 1737bc421f4fa428f65043bbb1300b98a58ec27e..03a271ca8c61a5ec1e30bf366a8c7cfcc23cf7c0 100644 (file)
--- a/error.c
+++ b/error.c
@@ -61,110 +61,24 @@ C).  The Perl level won't use all of this.
 =cut
 */
 
-#include "image.h"
+#include "imageri.h"
 #include <stdio.h>
 #include <stdlib.h>
 
-/* we never actually use the last item - it's the NULL terminator */
-#define ERRSTK 20
-i_errmsg error_stack[ERRSTK];
-int error_sp = ERRSTK - 1;
-/* we track the amount of space used each string, so we don't reallocate 
-   space unless we need to.
-   This also means that a memory tracking library may see the memory 
-   allocated for this as a leak. */
-int error_space[ERRSTK];
-
-static i_error_cb error_cb;
-static i_failed_cb failed_cb;
-static int failures_fatal;
-static char *argv0;
-
-/*
-=item i_set_argv0(char const *program)
-
-Sets the name of the program to be displayed in fatal error messages.
-
-The simplest way to use this is just:
-
-  i_set_argv0(argv[0]);
-
-when your program starts.
-*/
-void i_set_argv0(char const *name) {
-  char *dupl;
-  if (!name)
-    return;
-  dupl = mymalloc(strlen(name)+1);
-  strcpy(dupl, name);
-  if (argv0)
-    myfree(argv0);
-  argv0 = dupl;
-}
-
-/*
-=item i_set_failure_fatal(int failure_fatal)
-
-If failure_fatal is non-zero then any future failures will result in
-Imager exiting your program with a message describing the failure.
-
-Returns the previous setting.
-
-=cut
-*/
-int i_set_failures_fatal(int fatal) {
-  int old = failures_fatal;
-  failures_fatal = fatal;
-
-  return old;
-}
-
-/*
-=item i_set_error_cb(i_error_cb)
-
-Sets a callback function that is called each time an error is pushed
-onto the error stack.
-
-Returns the previous callback.
-
-i_set_failed_cb() is probably more useful.
-
-=cut
-*/
-i_error_cb i_set_error_cb(i_error_cb cb) {
-  i_error_cb old = error_cb;
-  error_cb = cb;
-
-  return old;
-}
-
-/*
-=item i_set_failed_cb(i_failed_cb cb)
-
-Sets a callback function that is called each time an Imager function
-fails.
-
-Returns the previous callback.
-
-=cut
-*/
-i_failed_cb i_set_failed_cb(i_failed_cb cb) {
-  i_failed_cb old = failed_cb;
-  failed_cb = cb;
-
-  return old;
-}
-
 /*
-=item i_errors()
+=item im_errors(ctx)
+=synopsis i_errmsg *errors = im_errors(aIMCTX);
+=synopsis i_errmsg *errors = i_errors();
 
 Returns a pointer to the first element of an array of error messages,
 terminated by a NULL pointer.  The highest level message is first.
 
+Also callable as C<i_errors()>.
+
 =cut
 */
-i_errmsg *i_errors() {
-  return error_stack + error_sp;
+i_errmsg *im_errors(im_context_t ctx) {
+  return ctx->error_stack + ctx->error_sp;
 }
 
 /*
@@ -180,30 +94,46 @@ the mark.
 
 =over
 
-=item i_clear_error()
+=item im_clear_error(ctx)
+X<im_clear_error API>X<i_clear_error API>
+=synopsis im_clear_error(aIMCTX);
+=synopsis i_clear_error();
+=category Error handling
+
+Clears the error stack.
+
+Called by any Imager function before doing any other processing.
+
+Also callable as C<i_clear_error()>.
 
-Called by any imager function before doing any other processing.
+=cut
+*/
 
-=cut */
-void i_clear_error() {
+void
+im_clear_error(im_context_t ctx) {
 #ifdef IMAGER_DEBUG_MALLOC
   int i;
 
-  for (i = 0; i < ERRSTK; ++i) {
-    if (error_space[i]) {
-      myfree(error_stack[i].msg);
-      error_stack[i].msg = NULL;
-      error_space[i] = 0;
+  for (i = 0; i < IM_ERROR_COUNT; ++i) {
+    if (ctx->error_space[i]) {
+      myfree(ctx->error_stack[i].msg);
+      ctx->error_stack[i].msg = NULL;
+      ctx->error_space[i] = 0;
     }
   }
 #endif
-  error_sp = ERRSTK-1;
+  ctx->error_sp = IM_ERROR_COUNT-1;
 }
 
 /*
-=item i_push_error(int code, char const *msg)
+=item im_push_error(ctx, code, message)
+X<im_push_error API>X<i_push_error API>
+=synopsis i_push_error(0, "Yep, it's broken");
+=synopsis i_push_error(errno, "Error writing");
+=synopsis im_push_error(aIMCTX, 0, "Something is wrong");
+=category Error handling
 
-Called by an imager function to push an error message onto the stack.
+Called by an Imager function to push an error message onto the stack.
 
 No message is pushed if the stack is full (since this means someone
 forgot to call i_clear_error(), or that a function that doesn't do
@@ -211,40 +141,52 @@ error handling is calling function that does.).
 
 =cut
 */
-void i_push_error(int code, char const *msg) {
-  int size = strlen(msg)+1;
+void
+im_push_error(im_context_t ctx, int code, char const *msg) {
+  size_t size = strlen(msg)+1;
 
-  if (error_sp <= 0)
+  if (ctx->error_sp <= 0)
     /* bad, bad programmer */
     return;
 
-  --error_sp;
-  if (error_space[error_sp] < size) {
-    if (error_stack[error_sp].msg)
-      myfree(error_stack[error_sp].msg);
-    /* memory allocated on the following line is only ever release when 
+  --ctx->error_sp;
+  if (ctx->error_alloc[ctx->error_sp] < size) {
+    if (ctx->error_stack[ctx->error_sp].msg)
+      myfree(ctx->error_stack[ctx->error_sp].msg);
+    /* memory allocated on the following line is only ever released when 
        we need a bigger string */
-    error_stack[error_sp].msg = mymalloc(size);
-    error_space[error_sp] = size;
+    /* size is size (len+1) of an existing string, overflow would mean
+       the system is broken anyway */
+    ctx->error_stack[ctx->error_sp].msg = mymalloc(size); /* checked 17jul05 tonyc */
+    ctx->error_alloc[ctx->error_sp] = size;
   }
-  strcpy(error_stack[error_sp].msg, msg);
-  error_stack[error_sp].code = code;
-
-  if (error_cb)
-    error_cb(code, msg);
+  strcpy(ctx->error_stack[ctx->error_sp].msg, msg);
+  ctx->error_stack[ctx->error_sp].code = code;
 }
 
 /*
-=item i_push_errorvf(int code, char const *fmt, va_list ap)
+=item im_push_errorvf(ctx, code, format, args)
+X<im_push_error_vf API>X<i_push_errorvf API>
+=synopsis va_args args;
+=synopsis va_start(args, lastarg);
+=synopsis im_push_errorvf(ctx, code, format, args);
+=category Error handling
 
 Intended for use by higher level functions, takes a varargs pointer
 and a format to produce the finally pushed error message.
 
+Does not support perl specific format codes.
+
+Also callable as C<i_push_errorvf(code, format, args)>
+
 =cut
 */
-void i_push_errorvf(int code, char const *fmt, va_list ap) {
+void 
+im_push_errorvf(im_context_t ctx, int code, char const *fmt, va_list ap) {
   char buf[1024];
-#if defined(_MSC_VER)
+#if defined(IMAGER_VSNPRINTF)
+  vsnprintf(buf, sizeof(buf), fmt, ap);
+#elif defined(_MSC_VER)
   _vsnprintf(buf, sizeof(buf), fmt, ap);
 #else
   /* is there a way to detect vsnprintf()? 
@@ -253,23 +195,50 @@ void i_push_errorvf(int code, char const *fmt, va_list ap) {
    */
   vsprintf(buf, fmt, ap);
 #endif
-  i_push_error(code, buf);
+  im_push_error(ctx, code, buf);
 }
 
 /*
 =item i_push_errorf(int code, char const *fmt, ...)
+=synopsis i_push_errorf(errno, "Cannot open file %s: %d", filename, errno);
+=category Error handling
 
-A version of i_push_error() that does printf() like formating.
+A version of i_push_error() that does printf() like formatting.
+
+Does not support perl specific format codes.
 
 =cut
 */
-void i_push_errorf(int code, char const *fmt, ...) {
+void
+i_push_errorf(int code, char const *fmt, ...) {
   va_list ap;
   va_start(ap, fmt);
   i_push_errorvf(code, fmt, ap);
   va_end(ap);
 }
 
+/*
+=item im_push_errorf(ctx, code, char const *fmt, ...)
+=synopsis im_push_errorf(aIMCTX, errno, "Cannot open file %s: %d", filename, errno);
+=category Error handling
+
+A version of im_push_error() that does printf() like formatting.
+
+Does not support perl specific format codes.
+
+=cut
+*/
+void
+im_push_errorf(im_context_t ctx, int code, char const *fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  im_push_errorvf(ctx, code, fmt, ap);
+  va_end(ap);
+}
+
+#ifdef IMAGER_I_FAILED
+#error "This isn't used and is untested"
+
 /*
 =item i_failed(char const *msg)
 
@@ -292,7 +261,7 @@ int i_failed(int code, char const *msg) {
     failed_cb(error_stack + error_sp);
   if (failures_fatal) {
     int sp;
-    int total; /* total length of error messages */
+    size_t total; /* total length of error messages */
     char *full; /* full message for logging */
     if (argv0)
       fprintf(stderr, "%s: ", argv0);
@@ -303,10 +272,14 @@ int i_failed(int code, char const *msg) {
       ++sp;
     }
     /* we want to log the error too, build an error message to hand to
-       m_fatal() */
+       i_fatal() */
     total = 1; /* remember the NUL */
     for (sp = error_sp; error_stack[sp].msg; ++sp) {
-      total += strlen(error_stack[sp].msg) + 2;
+      size_t new_total += strlen(error_stack[sp].msg) + 2;
+      if (new_total < total) {
+       /* overflow, somehow */
+       break;
+      }
     }
     full = mymalloc(total);
     if (!full) {
@@ -320,12 +293,35 @@ int i_failed(int code, char const *msg) {
     }
     /* lose the extra ": " */
     full[strlen(full)-2] = '\0';
-    m_fatal(EXIT_FAILURE, "%s", full);
+    i_fatal(EXIT_FAILURE, "%s", full);
   }
 
   return 0;
 }
 
+#endif
+
+#ifdef IM_ASSERT
+
+/*
+=item im_assert_fail(file, line, message)
+
+Called when an im_assert() assertion fails.
+
+Only available when Imager is built with assertions.
+
+=cut
+*/
+
+void
+im_assert_fail(char const *file, int line, char const *message) {
+  fprintf(stderr, "Assertion failed line %d file %s: %s\n", 
+         line, file, message);
+  abort();
+}
+
+#endif
+
 /*
 =back