polylib 5.22.8
errors.c
Go to the documentation of this file.
1/*
2 $Id: errors.c,v 1.6 2006/03/15 19:59:37 verdoolaege Exp $
3
4 Exception management.
5 See "arithmetic_errors.h".
6
7 $Log: errors.c,v $
8 Revision 1.6 2006/03/15 19:59:37 verdoolaege
9 arith: add some missing consts
10
11 Revision 1.5 2004/08/31 18:01:56 verdoolaege
12 remove warning
13
14 Revision 1.4 2004/02/11 10:19:54 verdoolaege
15 add const qualifier
16
17 Revision 1.3 2004/02/08 21:53:27 kienhuis
18 Update from Fabien Coelho, via Bart Kienhuis
19
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;-)
24
25 Revision 1.27 2003/09/04 09:40:37 coelho
26 init added.
27 verbosity mask added.
28
29 Revision 1.26 2003/09/03 14:05:20 coelho
30 push/pop callbacks called.
31
32 Revision 1.20 2003/08/18 09:55:09 coelho
33 get_exception_name added...
34
35 Revision 1.19 2003/06/13 13:59:07 coelho
36 const out.
37
38 Revision 1.18 2003/06/13 13:54:47 coelho
39 hop.
40
41 Revision 1.17 2002/04/02 08:44:54 coelho
42 timeout_error ajoute.
43
44 Revision 1.16 2000/10/27 13:26:03 ancourt
45 exception_thrown -> linear_number_of_exception_thrown
46
47 Revision 1.15 2000/07/27 15:21:55 coelho
48 message++
49
50 Revision 1.14 2000/07/27 14:59:59 coelho
51 trace added.
52
53 Revision 1.13 2000/07/26 08:41:23 coelho
54 the_last_just_thrown_exception management added.
55
56 Revision 1.12 1998/10/26 18:48:34 coelho
57 message++.
58
59 Revision 1.11 1998/10/26 14:38:06 coelho
60 constants back in.
61
62 Revision 1.10 1998/10/26 14:35:47 coelho
63 constants in .h.
64
65 Revision 1.9 1998/10/24 15:36:22 coelho
66 better exception error messages...
67
68 Revision 1.8 1998/10/24 15:19:17 coelho
69 more verbose throw...
70
71 Revision 1.7 1998/10/24 14:31:13 coelho
72 new stack implementation.
73 checks for matching catch/uncatch.
74 debug mode.
75
76 Revision 1.6 1998/10/24 09:31:06 coelho
77 RCS headers.
78 'const' tried.
79
80*/
81
82#include <stdio.h>
83#include <stdlib.h>
84#include <string.h>
85
86/* defined by configure script */
87/* #define THREAD_SAFE_POLYLIB */
88
89// #include "arithmetique.h"
91
92/* global constants to designate exceptions.
93 to be put in the type field bellow.
94 cproto 4.6 does not line 'const'...
95*/
96unsigned int overflow_error = 1;
97unsigned int simplex_arithmetic_error = 2;
98unsigned int user_exception_error = 4;
99unsigned int parser_exception_error = 8;
100unsigned int timeout_error = 16;
101
102/* catch all */
103unsigned int any_exception_error = ~0;
104
105/*
106 * On a few systems, type boolean and/or its values FALSE, TRUE may appear
107 * in standard header files. Or you may have conflicts with application-
108 * specific header files that you want to include together with these files.
109 * Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
110 */
111
112#ifndef HAVE_BOOLEAN
113typedef int boolean;
114#endif
115#ifndef FALSE /* in case these macros already exist */
116#define FALSE 0 /* values of boolean */
117#endif
118#ifndef TRUE
119#define TRUE 1
120#endif
121
122const char *get_exception_name(unsigned int exception) {
123 if (exception == overflow_error)
124 return "overflow_error exception";
125 if (exception == simplex_arithmetic_error)
126 return "simplex_arithmetic_error exception";
127 if (exception == user_exception_error)
128 return "user_exception_error exception";
129 if (exception == parser_exception_error)
130 return "parser_exception_error exception";
131 if (exception == timeout_error)
132 return "timeout_error exception";
133 if (exception == any_exception_error)
134 return "all exceptions mask";
135
136 return "unknown or mixed exception";
137}
138
139/* keep track of last thrown exception for RETHROW()
140 */
142
143/* whether to run in debug mode (that is to trace catch/uncatch/throw)
144 */
146static unsigned int linear_exception_verbose = 1 | 2 | 16;
147
148/* A structure for the exception stack.
149 */
150typedef struct {
151 /* exception type.
152 */
153 int what;
154
155 /* where to jump to.
156 */
157 jmp_buf where;
158
159 /* location of the CATCH to be matched against the UNCATCH.
160 */
161 const char *function;
162 const char *file;
163 int line;
165
166#define MAX_STACKED_CONTEXTS 64
167
168/***************************************************/
169/** Vincent's patch to enable POSIX multithreading */
170/** Feb. 2012 */
171/***************************************************/
172#ifdef THREAD_SAFE_POLYLIB
173#include <assert.h>
174#include <pthread.h>
175
176static pthread_once_t once_control = PTHREAD_ONCE_INIT;
177static pthread_key_t mt_key;
178/* (int)exception_index is stored in the last+1 exception stack position */
179#define exception_index (exception_stack[MAX_STACKED_CONTEXTS].what)
180static linear_exception_holder *allocate_local_stack(void) {
183 malloc(sizeof(linear_exception_holder) * (MAX_STACKED_CONTEXTS + 1));
184 assert(exception_stack != NULL);
185 exception_index = 0;
186 assert(pthread_setspecific(mt_key, exception_stack) == 0);
187 return (exception_stack);
188}
189static void free_local_stack(void *es) {
190 free(es);
191 assert(pthread_setspecific(mt_key, NULL) == 0);
192}
193static void init_multithreaded_stacks(void) {
194 pthread_key_create(&mt_key, free_local_stack);
195}
196#else // NO THREAD_SAFE_POLYLIB
197
198/* exception stack.
199 maximum extension.
200 current index (next available bucket)
201 */
203static int exception_index = 0;
204
205#endif // THREAD_SAFE_POLYLIB
206
208#ifdef THREAD_SAFE_POLYLIB
209 assert(pthread_once(&once_control, init_multithreaded_stacks) == 0);
211 if ((exception_stack = pthread_getspecific(mt_key)) != NULL)
212 free_local_stack(exception_stack);
213#endif // THREAD_SAFE_POLYLIB
214 return;
215}
216
217/* callbacks...
218 */
221
224 if (push_callback != NULL || pop_callback != NULL) {
225 fprintf(stderr, "exception callbacks already defined! (%p, %p)\n",
227 abort();
228 }
229
230 push_callback = push;
231 pop_callback = pop;
232}
233
234/* total number of exceptions thrown, for statistics.
235 */
237
238/* dump stack
239 */
241 int i;
242#ifdef THREAD_SAFE_POLYLIB
244 if ((exception_stack = pthread_getspecific(mt_key)) == NULL)
245 exception_stack = allocate_local_stack();
246#endif // THREAD_SAFE_POLYLIB
247
248 fprintf(f, "[dump_exception_stack_to_file] size=%d\n", exception_index);
249 for (i = 0; i < exception_index; i++) {
250 fprintf(f, "%d: [%s:%d in %s (%d)]\n", i, exception_stack[i].file,
251 exception_stack[i].line, exception_stack[i].function,
252 exception_stack[i].what);
253 }
254 fprintf(f, "\n");
255}
256
258
259#define exception_debug_message(type) \
260 fprintf(stderr, "%s[%s:%d %s (%s)/%d]\n", type, file, line, function, \
261 get_exception_name(what), exception_index)
262
263#define exception_debug_trace(type) \
264 if (linear_exception_debug_mode) { \
265 exception_debug_message(type); \
266 }
267
268/* push a what exception on stack.
269 */
270jmp_buf *push_exception_on_stack(int what, const char *function,
271 const char *file, int line) {
272#ifdef THREAD_SAFE_POLYLIB
273 assert(pthread_once(&once_control, init_multithreaded_stacks) == 0);
275 if ((exception_stack = pthread_getspecific(mt_key)) == NULL)
276 exception_stack = allocate_local_stack();
277#endif // THREAD_SAFE_POLYLIB
278
279 exception_debug_trace("PUSH ");
280
283 fprintf(stderr, "exception stack overflow\n");
285 abort();
286 }
287
288 if (push_callback)
289 push_callback(file, function, line);
290
292
297
299}
300
301#if !defined(same_string_p)
302#define same_string_p(s1, s2) (strcmp((s1), (s2)) == 0)
303#endif
304
305/* pop a what exception.
306 check for any mismatch!
307 */
308void pop_exception_from_stack(int what, const char *function, const char *file,
309 int line) {
310#ifdef THREAD_SAFE_POLYLIB
311 assert(pthread_once(&once_control, init_multithreaded_stacks) == 0);
313 if ((exception_stack = pthread_getspecific(mt_key)) == NULL)
314 exception_stack = allocate_local_stack();
315#endif // THREAD_SAFE_POLYLIB
316
317 exception_debug_trace("POP ");
318
319 if (exception_index == 0) {
321 fprintf(stderr, "exception stack underflow\n");
323 abort();
324 }
325
326 if (pop_callback)
327 pop_callback(file, function, line);
328
331
332 if ((exception_stack[exception_index].what != what) ||
334 !same_string_p(exception_stack[exception_index].function, function)) {
336 fprintf(stderr,
337 "exception stack mismatch at depth=%d:\n"
338 " CATCH: %s:%d in %s (%d)\n"
339 " UNCATCH: %s:%d in %s (%d)\n",
343 exception_stack[exception_index].what, file, line, function, what);
345 abort();
346 }
347}
348
349/* throws an exception of a given type by searching for
350 the specified 'what' in the current exception stack.
351*/
352void throw_exception(int what, const char *function, const char *file,
353 int line) {
354 int i;
355#ifdef THREAD_SAFE_POLYLIB
356 assert(pthread_once(&once_control, init_multithreaded_stacks) == 0);
358 if ((exception_stack = pthread_getspecific(mt_key)) == NULL)
359 exception_stack = allocate_local_stack();
360#endif // THREAD_SAFE_POLYLIB
361
362 exception_debug_trace("THROW");
363
364 the_last_just_thrown_exception = what; /* for rethrow */
365
366 for (i = exception_index - 1; i >= 0; i--) {
367 if (pop_callback)
368 /* pop with push parameters! */
369 pop_callback(exception_stack[i].file, exception_stack[i].function,
370 exception_stack[i].line);
371
372 if (exception_stack[i].what & what) {
373 exception_index = i;
375
377 fprintf(stderr, "---->[%s:%d %s (%d)/%d]\n", exception_stack[i].file,
378 exception_stack[i].line, exception_stack[i].function,
379 exception_stack[i].what, i);
380
381 /* trace some exceptions... */
382 if (linear_exception_verbose & what)
383 fprintf(stderr, "exception %d/%d: %s(%s:%d) -> %s(%s:%d)\n", what,
384 exception_stack[i].what, function, file, line,
385 exception_stack[i].function, exception_stack[i].file,
386 exception_stack[i].line);
387
388 longjmp(exception_stack[i].where, 0);
389 }
390 }
391
392 /* error. */
394 fprintf(stderr, "exception not found in stack:\n"
395 "an exception was THROWN without a proper matching CATCH\n");
397 abort();
398}
399
400void linear_initialize_exception_stack(unsigned int verbose_exceptions,
403 linear_exception_verbose = verbose_exceptions;
404 set_exception_callbacks(push, pop);
405}
void(* exception_callback_t)(const char *, const char *, int)
#define assert(ex)
Definition: assert.h:16
static int linear_exception_debug_mode
Definition: errors.c:145
void linear_initialize_exception_stack(unsigned int verbose_exceptions, exception_callback_t push, exception_callback_t pop)
Definition: errors.c:400
void dump_exception_stack()
Definition: errors.c:257
unsigned int user_exception_error
Definition: errors.c:98
void throw_exception(int what, const char *function, const char *file, int line)
Definition: errors.c:352
int linear_number_of_exception_thrown
Definition: errors.c:236
unsigned int parser_exception_error
Definition: errors.c:99
unsigned int simplex_arithmetic_error
Definition: errors.c:97
unsigned int timeout_error
Definition: errors.c:100
static unsigned int linear_exception_verbose
Definition: errors.c:146
unsigned int any_exception_error
Definition: errors.c:103
void dump_exception_stack_to_file(FILE *f)
Definition: errors.c:240
static exception_callback_t pop_callback
Definition: errors.c:220
int boolean
Definition: errors.c:113
void free_exception_stack()
Definition: errors.c:207
#define exception_debug_trace(type)
Definition: errors.c:263
#define exception_debug_message(type)
Definition: errors.c:259
void set_exception_callbacks(exception_callback_t push, exception_callback_t pop)
Definition: errors.c:222
static exception_callback_t push_callback
Definition: errors.c:219
unsigned int the_last_just_thrown_exception
Definition: errors.c:141
const char * get_exception_name(unsigned int exception)
Definition: errors.c:122
#define FALSE
Definition: errors.c:116
#define MAX_STACKED_CONTEXTS
Definition: errors.c:166
#define same_string_p(s1, s2)
Definition: errors.c:302
static int exception_index
Definition: errors.c:203
static linear_exception_holder exception_stack[MAX_STACKED_CONTEXTS]
Vincent's patch to enable POSIX multithreading.
Definition: errors.c:202
void pop_exception_from_stack(int what, const char *function, const char *file, int line)
Definition: errors.c:308
unsigned int overflow_error
Definition: errors.c:96
jmp_buf * push_exception_on_stack(int what, const char *function, const char *file, int line)
Definition: errors.c:270
const char * file
Definition: errors.c:162
const char * function
Definition: errors.c:161