=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
-static i_errmsg error_stack[ERRSTK];
-static 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. */
-static int error_space[ERRSTK];
-
+#if 0
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)
return old;
}
+#endif
+
/*
=item 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;
+}
+
+i_errmsg *i_errors(void) {
+ return im_errors(im_get_context());
}
/*
=over
=item i_clear_error()
+=synopsis i_clear_error();
+=category Error handling
+
+Clears the error stack.
+
+Called by any Imager function before doing any other processing.
-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)
+=synopsis i_push_error(0, "Yep, it's broken");
+=synopsis i_push_error(errno, "Error writing");
+=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
=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);
+ --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 */
/* size is size (len+1) of an existing string, overflow would mean
the system is broken anyway */
- error_stack[error_sp].msg = mymalloc(size); /* checked 17jul05 tonyc */
- error_space[error_sp] = size;
+ 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;
+ strcpy(ctx->error_stack[ctx->error_sp].msg, msg);
+ ctx->error_stack[ctx->error_sp].code = code;
+}
+
+#if 0
- if (error_cb)
- error_cb(code, msg);
+void
+i_push_error(int code, char const *msg) {
+ im_push_error(im_get_context(), code, msg);
}
+#endif
+
/*
-=item i_push_errorvf(int code, char const *fmt, va_list ap)
+=item i_push_errorvf(int C<code>, char const *C<fmt>, va_list C<ap>)
+
+=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.
+
=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()?
*/
vsprintf(buf, fmt, ap);
#endif
- i_push_error(code, buf);
+ im_push_error(ctx, code, buf);
+}
+
+void
+(i_push_errorvf)(int code, char const *fmt, va_list ap) {
+ im_push_errorvf(im_get_context(), code, fmt, ap);
}
/*
=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);
}
+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"
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);
++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) {
}
/* lose the extra ": " */
full[strlen(full)-2] = '\0';
- m_fatal(EXIT_FAILURE, "%s", full);
+ i_fatal(EXIT_FAILURE, "%s", full);
}
return 0;
#endif
+/*
+=item im_assert_fail(file, line, message)
+
+Called when an im_assert() assertion fails.
+
+=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();
+}
+
/*
=back