4 error.c - error reporting code for Imager
9 int new_fatal; // non-zero if errors are fatal
10 int old_fatal = i_set_failure_fatal(new_fatal);
11 i_set_argv0("name of your program");
12 extern void error_cb(char const *);
14 old_ecb = i_set_error_cb(error_cb);
16 extern void failed_cb(char **errors);
17 old_fcb = i_set_failed_cb(failed_cb);
18 if (!i_something(...)) {
19 char **errors = i_errors();
23 undef_int i_something(...) {
25 if (!some_lower_func(...)) {
26 return i_failed("could not something");
30 undef_int some_lower_func(...) {
31 if (somethingelse_failed()) {
32 i_push_error("could not somethingelse");
40 This module provides the C level error handling functionality for
43 A few functions return or pass in an i_errmsg *, this is list of error
44 structures, terminated by an entry with a NULL msg value, each of
45 which contains a msg and an error code. Even though these aren't
46 passed as i_errmsg const * pointers, don't modify the strings
49 The interface as currently defined isn't thread safe, unfortunately.
51 This code uses Imager's mymalloc() for memory allocation, so out of
52 memory errors are I<always> fatal.
56 These functions form the interface that a user of Imager sees (from
57 C). The Perl level won't use all of this.
70 =synopsis i_errmsg *errors = im_errors(aIMCTX);
71 =synopsis i_errmsg *errors = i_errors();
73 Returns a pointer to the first element of an array of error messages,
74 terminated by a NULL pointer. The highest level message is first.
76 Also callable as C<i_errors()>.
80 i_errmsg *im_errors(im_context_t ctx) {
81 return ctx->error_stack + ctx->error_sp;
87 =head1 INTERNAL FUNCTIONS
89 These functions are called by Imager to report errors through the
92 It may be desirable to have functions to mark the stack and reset to
97 =item im_clear_error(ctx)
98 X<im_clear_error API>X<i_clear_error API>
99 =synopsis im_clear_error(aIMCTX);
100 =synopsis i_clear_error();
101 =category Error handling
103 Clears the error stack.
105 Called by any Imager function before doing any other processing.
107 Also callable as C<i_clear_error()>.
113 im_clear_error(im_context_t ctx) {
114 #ifdef IMAGER_DEBUG_MALLOC
117 for (i = 0; i < IM_ERROR_COUNT; ++i) {
118 if (ctx->error_space[i]) {
119 myfree(ctx->error_stack[i].msg);
120 ctx->error_stack[i].msg = NULL;
121 ctx->error_space[i] = 0;
125 ctx->error_sp = IM_ERROR_COUNT-1;
129 =item im_push_error(ctx, code, message)
130 X<im_push_error API>X<i_push_error API>
131 =synopsis i_push_error(0, "Yep, it's broken");
132 =synopsis i_push_error(errno, "Error writing");
133 =synopsis im_push_error(aIMCTX, 0, "Something is wrong");
134 =category Error handling
136 Called by an Imager function to push an error message onto the stack.
138 No message is pushed if the stack is full (since this means someone
139 forgot to call i_clear_error(), or that a function that doesn't do
140 error handling is calling function that does.).
145 im_push_error(im_context_t ctx, int code, char const *msg) {
146 size_t size = strlen(msg)+1;
148 if (ctx->error_sp <= 0)
149 /* bad, bad programmer */
153 if (ctx->error_alloc[ctx->error_sp] < size) {
154 if (ctx->error_stack[ctx->error_sp].msg)
155 myfree(ctx->error_stack[ctx->error_sp].msg);
156 /* memory allocated on the following line is only ever released when
157 we need a bigger string */
158 /* size is size (len+1) of an existing string, overflow would mean
159 the system is broken anyway */
160 ctx->error_stack[ctx->error_sp].msg = mymalloc(size); /* checked 17jul05 tonyc */
161 ctx->error_alloc[ctx->error_sp] = size;
163 strcpy(ctx->error_stack[ctx->error_sp].msg, msg);
164 ctx->error_stack[ctx->error_sp].code = code;
168 =item im_push_errorvf(ctx, code, format, args)
169 X<im_push_error_vf API>X<i_push_errorvf API>
170 =synopsis va_args args;
171 =synopsis va_start(args, lastarg);
172 =synopsis im_push_errorvf(ctx, code, format, args);
173 =category Error handling
175 Intended for use by higher level functions, takes a varargs pointer
176 and a format to produce the finally pushed error message.
178 Does not support perl specific format codes.
180 Also callable as C<i_push_errorvf(code, format, args)>
185 im_push_errorvf(im_context_t ctx, int code, char const *fmt, va_list ap) {
187 #if defined(IMAGER_VSNPRINTF)
188 vsnprintf(buf, sizeof(buf), fmt, ap);
189 #elif defined(_MSC_VER)
190 _vsnprintf(buf, sizeof(buf), fmt, ap);
192 /* is there a way to detect vsnprintf()?
193 for this and other functions we need some mechanism to handle
194 detection (like perl's Configure, or autoconf)
196 vsprintf(buf, fmt, ap);
198 im_push_error(ctx, code, buf);
202 =item i_push_errorf(int code, char const *fmt, ...)
203 =synopsis i_push_errorf(errno, "Cannot open file %s: %d", filename, errno);
204 =category Error handling
206 A version of i_push_error() that does printf() like formatting.
208 Does not support perl specific format codes.
213 i_push_errorf(int code, char const *fmt, ...) {
216 i_push_errorvf(code, fmt, ap);
221 =item im_push_errorf(ctx, code, char const *fmt, ...)
222 =synopsis im_push_errorf(aIMCTX, errno, "Cannot open file %s: %d", filename, errno);
223 =category Error handling
225 A version of im_push_error() that does printf() like formatting.
227 Does not support perl specific format codes.
232 im_push_errorf(im_context_t ctx, int code, char const *fmt, ...) {
235 im_push_errorvf(ctx, code, fmt, ap);
239 #ifdef IMAGER_I_FAILED
240 #error "This isn't used and is untested"
243 =item i_failed(char const *msg)
245 Called by Imager code to indicate that a top-level has failed.
247 msg can be NULL, in which case no error is pushed.
249 Calls the current failed callback, if any.
251 Aborts the program with an error, if failures have been set to be fatal.
253 Returns zero if it does not abort.
257 int i_failed(int code, char const *msg) {
259 i_push_error(code, msg);
261 failed_cb(error_stack + error_sp);
262 if (failures_fatal) {
264 size_t total; /* total length of error messages */
265 char *full; /* full message for logging */
267 fprintf(stderr, "%s: ", argv0);
268 fputs("error:\n", stderr);
270 while (error_stack[sp].msg) {
271 fprintf(stderr, " %s\n", error_stack[sp].msg);
274 /* we want to log the error too, build an error message to hand to
276 total = 1; /* remember the NUL */
277 for (sp = error_sp; error_stack[sp].msg; ++sp) {
278 size_t new_total += strlen(error_stack[sp].msg) + 2;
279 if (new_total < total) {
280 /* overflow, somehow */
284 full = mymalloc(total);
286 /* just quit, at least it's on stderr */
290 for (sp = error_sp; error_stack[sp].msg; ++sp) {
291 strcat(full, error_stack[sp].msg);
294 /* lose the extra ": " */
295 full[strlen(full)-2] = '\0';
296 i_fatal(EXIT_FAILURE, "%s", full);
305 =item im_assert_fail(file, line, message)
307 Called when an im_assert() assertion fails.
313 im_assert_fail(char const *file, int line, char const *message) {
314 fprintf(stderr, "Assertion failed line %d file %s: %s\n",
315 line, file, message);
324 This interface isn't thread safe.
328 Tony Cook <tony@develop-help.com>
330 Stack concept by Arnar Mar Hrafnkelsson <addi@umich.edu>