2 This file is part of PolyLib.
4 PolyLib is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 PolyLib is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with PolyLib. If not, see <http://www.gnu.org/licenses/>.
19 $Id: errors.c,v 1.6 2006/03/15 19:59:37 verdoolaege Exp $
22 See "arithmetic_errors.h".
25 Revision 1.6 2006/03/15 19:59:37 verdoolaege
26 arith: add some missing consts
28 Revision 1.5 2004/08/31 18:01:56 verdoolaege
31 Revision 1.4 2004/02/11 10:19:54 verdoolaege
34 Revision 1.3 2004/02/08 21:53:27 kienhuis
35 Update from Fabien Coelho, via Bart Kienhuis
37 I've updated here in the C3/Linear library the arithmetic_error
38 package that I developped (with others) to handle exceptions in C.
39 It adds a simple callback feature which is needed for pips here.
40 If you do not use it, it should not harm;-)
42 Revision 1.27 2003/09/04 09:40:37 coelho
46 Revision 1.26 2003/09/03 14:05:20 coelho
47 push/pop callbacks called.
49 Revision 1.20 2003/08/18 09:55:09 coelho
50 get_exception_name added...
52 Revision 1.19 2003/06/13 13:59:07 coelho
55 Revision 1.18 2003/06/13 13:54:47 coelho
58 Revision 1.17 2002/04/02 08:44:54 coelho
61 Revision 1.16 2000/10/27 13:26:03 ancourt
62 exception_thrown -> linear_number_of_exception_thrown
64 Revision 1.15 2000/07/27 15:21:55 coelho
67 Revision 1.14 2000/07/27 14:59:59 coelho
70 Revision 1.13 2000/07/26 08:41:23 coelho
71 the_last_just_thrown_exception management added.
73 Revision 1.12 1998/10/26 18:48:34 coelho
76 Revision 1.11 1998/10/26 14:38:06 coelho
79 Revision 1.10 1998/10/26 14:35:47 coelho
82 Revision 1.9 1998/10/24 15:36:22 coelho
83 better exception error messages...
85 Revision 1.8 1998/10/24 15:19:17 coelho
88 Revision 1.7 1998/10/24 14:31:13 coelho
89 new stack implementation.
90 checks for matching catch/uncatch.
93 Revision 1.6 1998/10/24 09:31:06 coelho
103 /* defined by configure script */
104 /* #define THREAD_SAFE_POLYLIB */
106 #include "arithmetique.h"
108 /* global constants to designate exceptions.
109 to be put in the type field bellow.
110 cproto 4.6 does not line 'const'...
112 unsigned int overflow_error
= 1;
113 unsigned int simplex_arithmetic_error
= 2;
114 unsigned int user_exception_error
= 4;
115 unsigned int parser_exception_error
= 8;
116 unsigned int timeout_error
= 16;
119 unsigned int any_exception_error
= ~0;
123 * On a few systems, type boolean and/or its values FALSE, TRUE may appear
124 * in standard header files. Or you may have conflicts with application-
125 * specific header files that you want to include together with these files.
126 * Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
132 #ifndef FALSE /* in case these macros already exist */
133 #define FALSE 0 /* values of boolean */
139 const char *get_exception_name(unsigned int exception
)
141 if (exception
==overflow_error
)
142 return "overflow_error exception";
143 if (exception
==simplex_arithmetic_error
)
144 return "simplex_arithmetic_error exception";
145 if (exception
==user_exception_error
)
146 return "user_exception_error exception";
147 if (exception
==parser_exception_error
)
148 return "parser_exception_error exception";
149 if (exception
==timeout_error
)
150 return "timeout_error exception";
151 if (exception
==any_exception_error
)
152 return "all exceptions mask";
154 return "unknown or mixed exception";
157 /* keep track of last thrown exception for RETHROW()
159 unsigned int the_last_just_thrown_exception
= 0;
161 /* whether to run in debug mode (that is to trace catch/uncatch/throw)
163 static int linear_exception_debug_mode
= FALSE
;
164 static unsigned int linear_exception_verbose
= 1 | 2 | 16 ;
166 /* A structure for the exception stack.
178 /* location of the CATCH to be matched against the UNCATCH.
180 const char * function
;
184 linear_exception_holder
;
186 #define MAX_STACKED_CONTEXTS 64
189 /***************************************************/
190 /** Vincent's patch to enable POSIX multithreading */
192 /***************************************************/
193 #ifdef THREAD_SAFE_POLYLIB
197 static pthread_once_t once_control
= PTHREAD_ONCE_INIT
;
198 static pthread_key_t mt_key
;
199 /* (int)exception_index is stored in the last+1 exception stack position */
200 #define exception_index (exception_stack[MAX_STACKED_CONTEXTS].what)
201 static linear_exception_holder
*allocate_local_stack(void)
203 linear_exception_holder
*exception_stack
;
204 exception_stack
= malloc( sizeof(linear_exception_holder
)*(MAX_STACKED_CONTEXTS
+1) );
205 assert( exception_stack
!=NULL
);
207 assert( pthread_setspecific( mt_key
, exception_stack
) == 0 );
208 return( exception_stack
);
210 static void free_local_stack(void *es
)
213 assert( pthread_setspecific(mt_key
, NULL
) == 0 );
215 static void init_multithreaded_stacks(void)
217 pthread_key_create(&mt_key
, free_local_stack
);
219 #else // NO THREAD_SAFE_POLYLIB
223 current index (next available bucket)
225 static linear_exception_holder exception_stack
[MAX_STACKED_CONTEXTS
];
226 static int exception_index
= 0;
228 #endif // THREAD_SAFE_POLYLIB
232 static exception_callback_t push_callback
= NULL
;
233 static exception_callback_t pop_callback
= NULL
;
235 void set_exception_callbacks(exception_callback_t push
,
236 exception_callback_t pop
)
238 if (push_callback
!=NULL
|| pop_callback
!=NULL
)
240 fprintf(stderr
, "exception callbacks already defined! (%p, %p)\n",
241 push_callback
, pop_callback
);
245 push_callback
= push
;
249 /* total number of exceptions thrown, for statistics.
251 int linear_number_of_exception_thrown
= 0;
255 void dump_exception_stack_to_file(FILE * f
)
258 #ifdef THREAD_SAFE_POLYLIB
259 linear_exception_holder
*exception_stack
;
260 if( (exception_stack
= pthread_getspecific( mt_key
)) == NULL
)
261 exception_stack
= allocate_local_stack();
262 #endif // THREAD_SAFE_POLYLIB
264 fprintf(f
, "[dump_exception_stack_to_file] size=%d\n", exception_index
);
265 for (i
=0; i
<exception_index
; i
++)
268 "%d: [%s:%d in %s (%d)]\n",
270 exception_stack
[i
].file
,
271 exception_stack
[i
].line
,
272 exception_stack
[i
].function
,
273 exception_stack
[i
].what
);
278 void dump_exception_stack()
280 dump_exception_stack_to_file(stderr
);
283 #define exception_debug_message(type) \
284 fprintf(stderr, "%s[%s:%d %s (%s)/%d]\n", \
285 type, file, line, function, get_exception_name(what), exception_index)
287 #define exception_debug_trace(type) \
288 if (linear_exception_debug_mode) { exception_debug_message(type); }
290 /* push a what exception on stack.
293 push_exception_on_stack(
295 const char * function
,
299 #ifdef THREAD_SAFE_POLYLIB
300 assert(pthread_once(&once_control
, init_multithreaded_stacks
) == 0);
301 linear_exception_holder
*exception_stack
;
302 if( (exception_stack
= pthread_getspecific( mt_key
)) == NULL
)
303 exception_stack
= allocate_local_stack();
304 #endif // THREAD_SAFE_POLYLIB
306 exception_debug_trace("PUSH ");
309 if (exception_index
==MAX_STACKED_CONTEXTS
)
311 exception_debug_message("push");
312 fprintf(stderr
, "exception stack overflow\n");
313 dump_exception_stack();
317 if (push_callback
) push_callback(file
, function
, line
);
319 the_last_just_thrown_exception
= 0;
321 exception_stack
[exception_index
].what
= what
;
322 exception_stack
[exception_index
].function
= function
;
323 exception_stack
[exception_index
].file
= file
;
324 exception_stack
[exception_index
].line
= line
;
326 return & exception_stack
[exception_index
++].where
;
329 #if !defined(same_string_p)
330 #define same_string_p(s1, s2) (strcmp((s1),(s2))==0)
333 /* pop a what exception.
334 check for any mismatch!
337 pop_exception_from_stack(
339 const char * function
,
343 #ifdef THREAD_SAFE_POLYLIB
344 assert(pthread_once(&once_control
, init_multithreaded_stacks
) == 0);
345 linear_exception_holder
*exception_stack
;
346 if( (exception_stack
= pthread_getspecific( mt_key
)) == NULL
)
347 exception_stack
= allocate_local_stack();
348 #endif // THREAD_SAFE_POLYLIB
350 exception_debug_trace("POP ");
352 if (exception_index
==0)
354 exception_debug_message("pop");
355 fprintf(stderr
, "exception stack underflow\n");
356 dump_exception_stack();
360 if (pop_callback
) pop_callback(file
, function
, line
);
363 the_last_just_thrown_exception
= 0;
365 if ((exception_stack
[exception_index
].what
!= what
) ||
366 !same_string_p(exception_stack
[exception_index
].file
, file
) ||
367 !same_string_p(exception_stack
[exception_index
].function
, function
))
369 exception_debug_message("pop");
371 "exception stack mismatch at depth=%d:\n"
372 " CATCH: %s:%d in %s (%d)\n"
373 " UNCATCH: %s:%d in %s (%d)\n",
375 exception_stack
[exception_index
].file
,
376 exception_stack
[exception_index
].line
,
377 exception_stack
[exception_index
].function
,
378 exception_stack
[exception_index
].what
,
379 file
, line
, function
, what
);
380 dump_exception_stack();
385 /* throws an exception of a given type by searching for
386 the specified 'what' in the current exception stack.
388 void throw_exception(
390 const char * function
,
395 #ifdef THREAD_SAFE_POLYLIB
396 assert(pthread_once(&once_control
, init_multithreaded_stacks
) == 0);
397 linear_exception_holder
*exception_stack
;
398 if( (exception_stack
= pthread_getspecific( mt_key
)) == NULL
)
399 exception_stack
= allocate_local_stack();
400 #endif // THREAD_SAFE_POLYLIB
402 exception_debug_trace("THROW");
404 the_last_just_thrown_exception
= what
; /* for rethrow */
406 for (i
=exception_index
-1; i
>=0; i
--)
409 /* pop with push parameters! */
410 pop_callback(exception_stack
[i
].file
,
411 exception_stack
[i
].function
,
412 exception_stack
[i
].line
);
414 if (exception_stack
[i
].what
& what
)
417 linear_number_of_exception_thrown
++;
419 if (linear_exception_debug_mode
)
420 fprintf(stderr
, "---->[%s:%d %s (%d)/%d]\n",
421 exception_stack
[i
].file
,
422 exception_stack
[i
].line
,
423 exception_stack
[i
].function
,
424 exception_stack
[i
].what
,
427 /* trace some exceptions... */
428 if (linear_exception_verbose
& what
)
429 fprintf(stderr
, "exception %d/%d: %s(%s:%d) -> %s(%s:%d)\n",
430 what
, exception_stack
[i
].what
,
431 function
, file
, line
,
432 exception_stack
[i
].function
,
433 exception_stack
[i
].file
,
434 exception_stack
[i
].line
);
436 longjmp(exception_stack
[i
].where
, 0);
441 exception_debug_message("throw");
443 "exception not found in stack:\n"
444 "an exception was THROWN without a proper matching CATCH\n");
445 dump_exception_stack();
449 void linear_initialize_exception_stack(
450 unsigned int verbose_exceptions
,
451 exception_callback_t push
,
452 exception_callback_t pop
)
454 linear_exception_verbose
= verbose_exceptions
;
455 set_exception_callbacks(push
, pop
);