autoconf warning missing files
[polylib.git] / source / arith / errors.c
blob2b0659eaa7434b64793ca43fc2cffb7eb288e575
1 /*
2 $Id: errors.c,v 1.6 2006/03/15 19:59:37 verdoolaege Exp $
4 Exception management.
5 See "arithmetic_errors.h".
7 $Log: errors.c,v $
8 Revision 1.6 2006/03/15 19:59:37 verdoolaege
9 arith: add some missing consts
11 Revision 1.5 2004/08/31 18:01:56 verdoolaege
12 remove warning
14 Revision 1.4 2004/02/11 10:19:54 verdoolaege
15 add const qualifier
17 Revision 1.3 2004/02/08 21:53:27 kienhuis
18 Update from Fabien Coelho, via Bart Kienhuis
20 I've updated here in the C3/Linear library the arithmetic_error
21 package that I developped (with others) to handle exceptions in C.
22 It adds a simple callback feature which is needed for pips here.
23 If you do not use it, it should not harm;-)
25 Revision 1.27 2003/09/04 09:40:37 coelho
26 init added.
27 verbosity mask added.
29 Revision 1.26 2003/09/03 14:05:20 coelho
30 push/pop callbacks called.
32 Revision 1.20 2003/08/18 09:55:09 coelho
33 get_exception_name added...
35 Revision 1.19 2003/06/13 13:59:07 coelho
36 const out.
38 Revision 1.18 2003/06/13 13:54:47 coelho
39 hop.
41 Revision 1.17 2002/04/02 08:44:54 coelho
42 timeout_error ajoute.
44 Revision 1.16 2000/10/27 13:26:03 ancourt
45 exception_thrown -> linear_number_of_exception_thrown
47 Revision 1.15 2000/07/27 15:21:55 coelho
48 message++
50 Revision 1.14 2000/07/27 14:59:59 coelho
51 trace added.
53 Revision 1.13 2000/07/26 08:41:23 coelho
54 the_last_just_thrown_exception management added.
56 Revision 1.12 1998/10/26 18:48:34 coelho
57 message++.
59 Revision 1.11 1998/10/26 14:38:06 coelho
60 constants back in.
62 Revision 1.10 1998/10/26 14:35:47 coelho
63 constants in .h.
65 Revision 1.9 1998/10/24 15:36:22 coelho
66 better exception error messages...
68 Revision 1.8 1998/10/24 15:19:17 coelho
69 more verbose throw...
71 Revision 1.7 1998/10/24 14:31:13 coelho
72 new stack implementation.
73 checks for matching catch/uncatch.
74 debug mode.
76 Revision 1.6 1998/10/24 09:31:06 coelho
77 RCS headers.
78 'const' tried.
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <string.h>
86 /* defined by configure script */
87 /* #define THREAD_SAFE_POLYLIB */
89 //#include "arithmetique.h"
90 #include <polylib/arithmetique.h>
92 /* global constants to designate exceptions.
93 to be put in the type field bellow.
94 cproto 4.6 does not line 'const'...
96 unsigned int overflow_error = 1;
97 unsigned int simplex_arithmetic_error = 2;
98 unsigned int user_exception_error = 4;
99 unsigned int parser_exception_error = 8;
100 unsigned int timeout_error = 16;
102 /* catch all */
103 unsigned int any_exception_error = ~0;
107 * On a few systems, type boolean and/or its values FALSE, TRUE may appear
108 * in standard header files. Or you may have conflicts with application-
109 * specific header files that you want to include together with these files.
110 * Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
113 #ifndef HAVE_BOOLEAN
114 typedef int boolean;
115 #endif
116 #ifndef FALSE /* in case these macros already exist */
117 #define FALSE 0 /* values of boolean */
118 #endif
119 #ifndef TRUE
120 #define TRUE 1
121 #endif
123 const char *get_exception_name(unsigned int exception)
125 if (exception==overflow_error)
126 return "overflow_error exception";
127 if (exception==simplex_arithmetic_error)
128 return "simplex_arithmetic_error exception";
129 if (exception==user_exception_error)
130 return "user_exception_error exception";
131 if (exception==parser_exception_error)
132 return "parser_exception_error exception";
133 if (exception==timeout_error)
134 return "timeout_error exception";
135 if (exception==any_exception_error)
136 return "all exceptions mask";
138 return "unknown or mixed exception";
141 /* keep track of last thrown exception for RETHROW()
143 unsigned int the_last_just_thrown_exception = 0;
145 /* whether to run in debug mode (that is to trace catch/uncatch/throw)
147 static int linear_exception_debug_mode = FALSE;
148 static unsigned int linear_exception_verbose = 1 | 2 | 16 ;
150 /* A structure for the exception stack.
152 typedef struct
154 /* exception type.
156 int what;
158 /* where to jump to.
160 jmp_buf where;
162 /* location of the CATCH to be matched against the UNCATCH.
164 const char * function;
165 const char * file;
166 int line;
168 linear_exception_holder;
170 #define MAX_STACKED_CONTEXTS 64
173 /***************************************************/
174 /** Vincent's patch to enable POSIX multithreading */
175 /** Feb. 2012 */
176 /***************************************************/
177 #ifdef THREAD_SAFE_POLYLIB
178 #include <pthread.h>
179 #include <assert.h>
181 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
182 static pthread_key_t mt_key;
183 /* (int)exception_index is stored in the last+1 exception stack position */
184 #define exception_index (exception_stack[MAX_STACKED_CONTEXTS].what)
185 static linear_exception_holder *allocate_local_stack(void)
187 linear_exception_holder *exception_stack;
188 exception_stack = malloc( sizeof(linear_exception_holder)*(MAX_STACKED_CONTEXTS+1) );
189 assert( exception_stack!=NULL );
190 exception_index = 0;
191 assert( pthread_setspecific( mt_key, exception_stack ) == 0 );
192 return( exception_stack );
194 static void free_local_stack(void *es)
196 free(es);
197 assert( pthread_setspecific(mt_key, NULL) == 0 );
199 static void init_multithreaded_stacks(void)
201 pthread_key_create(&mt_key, free_local_stack);
203 #else // NO THREAD_SAFE_POLYLIB
205 /* exception stack.
206 maximum extension.
207 current index (next available bucket)
209 static linear_exception_holder exception_stack[MAX_STACKED_CONTEXTS];
210 static int exception_index = 0;
212 #endif // THREAD_SAFE_POLYLIB
214 void free_exception_stack()
216 #ifdef THREAD_SAFE_POLYLIB
217 assert(pthread_once(&once_control, init_multithreaded_stacks) == 0);
218 linear_exception_holder *exception_stack;
219 if( (exception_stack = pthread_getspecific( mt_key )) != NULL )
220 free_local_stack(exception_stack);
221 #endif // THREAD_SAFE_POLYLIB
222 return;
225 /* callbacks...
227 static exception_callback_t push_callback = NULL;
228 static exception_callback_t pop_callback = NULL;
230 void set_exception_callbacks(exception_callback_t push,
231 exception_callback_t pop)
233 if (push_callback!=NULL || pop_callback!=NULL)
235 fprintf(stderr, "exception callbacks already defined! (%p, %p)\n",
236 push_callback, pop_callback);
237 abort();
240 push_callback = push;
241 pop_callback = pop;
244 /* total number of exceptions thrown, for statistics.
246 int linear_number_of_exception_thrown = 0;
248 /* dump stack
250 void dump_exception_stack_to_file(FILE * f)
252 int i;
253 #ifdef THREAD_SAFE_POLYLIB
254 linear_exception_holder *exception_stack;
255 if( (exception_stack = pthread_getspecific( mt_key )) == NULL )
256 exception_stack = allocate_local_stack();
257 #endif // THREAD_SAFE_POLYLIB
259 fprintf(f, "[dump_exception_stack_to_file] size=%d\n", exception_index);
260 for (i=0; i<exception_index; i++)
262 fprintf(f,
263 "%d: [%s:%d in %s (%d)]\n",
265 exception_stack[i].file,
266 exception_stack[i].line,
267 exception_stack[i].function,
268 exception_stack[i].what);
270 fprintf(f, "\n");
273 void dump_exception_stack()
275 dump_exception_stack_to_file(stderr);
278 #define exception_debug_message(type) \
279 fprintf(stderr, "%s[%s:%d %s (%s)/%d]\n", \
280 type, file, line, function, get_exception_name(what), exception_index)
282 #define exception_debug_trace(type) \
283 if (linear_exception_debug_mode) { exception_debug_message(type); }
285 /* push a what exception on stack.
287 jmp_buf *
288 push_exception_on_stack(
289 int what,
290 const char * function,
291 const char * file,
292 int line)
294 #ifdef THREAD_SAFE_POLYLIB
295 assert(pthread_once(&once_control, init_multithreaded_stacks) == 0);
296 linear_exception_holder *exception_stack;
297 if( (exception_stack = pthread_getspecific( mt_key )) == NULL )
298 exception_stack = allocate_local_stack();
299 #endif // THREAD_SAFE_POLYLIB
301 exception_debug_trace("PUSH ");
304 if (exception_index==MAX_STACKED_CONTEXTS)
306 exception_debug_message("push");
307 fprintf(stderr, "exception stack overflow\n");
308 dump_exception_stack();
309 abort();
312 if (push_callback) push_callback(file, function, line);
314 the_last_just_thrown_exception = 0;
316 exception_stack[exception_index].what = what;
317 exception_stack[exception_index].function = function;
318 exception_stack[exception_index].file = file;
319 exception_stack[exception_index].line = line;
321 return & exception_stack[exception_index++].where;
324 #if !defined(same_string_p)
325 #define same_string_p(s1, s2) (strcmp((s1),(s2))==0)
326 #endif
328 /* pop a what exception.
329 check for any mismatch!
331 void
332 pop_exception_from_stack(
333 int what,
334 const char * function,
335 const char * file,
336 int line)
338 #ifdef THREAD_SAFE_POLYLIB
339 assert(pthread_once(&once_control, init_multithreaded_stacks) == 0);
340 linear_exception_holder *exception_stack;
341 if( (exception_stack = pthread_getspecific( mt_key )) == NULL )
342 exception_stack = allocate_local_stack();
343 #endif // THREAD_SAFE_POLYLIB
345 exception_debug_trace("POP ");
347 if (exception_index==0)
349 exception_debug_message("pop");
350 fprintf(stderr, "exception stack underflow\n");
351 dump_exception_stack();
352 abort();
355 if (pop_callback) pop_callback(file, function, line);
357 exception_index--;
358 the_last_just_thrown_exception = 0;
360 if ((exception_stack[exception_index].what != what) ||
361 !same_string_p(exception_stack[exception_index].file, file) ||
362 !same_string_p(exception_stack[exception_index].function, function))
364 exception_debug_message("pop");
365 fprintf(stderr,
366 "exception stack mismatch at depth=%d:\n"
367 " CATCH: %s:%d in %s (%d)\n"
368 " UNCATCH: %s:%d in %s (%d)\n",
369 exception_index,
370 exception_stack[exception_index].file,
371 exception_stack[exception_index].line,
372 exception_stack[exception_index].function,
373 exception_stack[exception_index].what,
374 file, line, function, what);
375 dump_exception_stack();
376 abort();
380 /* throws an exception of a given type by searching for
381 the specified 'what' in the current exception stack.
383 void throw_exception(
384 int what,
385 const char * function,
386 const char * file,
387 int line)
389 int i;
390 #ifdef THREAD_SAFE_POLYLIB
391 assert(pthread_once(&once_control, init_multithreaded_stacks) == 0);
392 linear_exception_holder *exception_stack;
393 if( (exception_stack = pthread_getspecific( mt_key )) == NULL )
394 exception_stack = allocate_local_stack();
395 #endif // THREAD_SAFE_POLYLIB
397 exception_debug_trace("THROW");
399 the_last_just_thrown_exception = what; /* for rethrow */
401 for (i=exception_index-1; i>=0; i--)
403 if (pop_callback)
404 /* pop with push parameters! */
405 pop_callback(exception_stack[i].file,
406 exception_stack[i].function,
407 exception_stack[i].line);
409 if (exception_stack[i].what & what)
411 exception_index = i;
412 linear_number_of_exception_thrown++;
414 if (linear_exception_debug_mode)
415 fprintf(stderr, "---->[%s:%d %s (%d)/%d]\n",
416 exception_stack[i].file,
417 exception_stack[i].line,
418 exception_stack[i].function,
419 exception_stack[i].what,
422 /* trace some exceptions... */
423 if (linear_exception_verbose & what)
424 fprintf(stderr, "exception %d/%d: %s(%s:%d) -> %s(%s:%d)\n",
425 what, exception_stack[i].what,
426 function, file, line,
427 exception_stack[i].function,
428 exception_stack[i].file,
429 exception_stack[i].line);
431 longjmp(exception_stack[i].where, 0);
435 /* error. */
436 exception_debug_message("throw");
437 fprintf(stderr,
438 "exception not found in stack:\n"
439 "an exception was THROWN without a proper matching CATCH\n");
440 dump_exception_stack();
441 abort();
444 void linear_initialize_exception_stack(
445 unsigned int verbose_exceptions,
446 exception_callback_t push,
447 exception_callback_t pop)
449 linear_exception_verbose = verbose_exceptions;
450 set_exception_callbacks(push, pop);