polylib: errors.c Source File

- Main Page
- Classes
- Files

# errors.c

Go to the documentation of this file.

    00001 /*
    00002   $Id: errors.c,v 1.6 2006/03/15 19:59:37 verdoolaege Exp $
    00003
    00004   Exception management.
    00005   See "arithmetic_errors.h".
    00006
    00007   $Log: errors.c,v $
    00008   Revision 1.6  2006/03/15 19:59:37  verdoolaege
    00009   arith: add some missing consts
    00010
    00011   Revision 1.5  2004/08/31 18:01:56  verdoolaege
    00012   remove warning
    00013
    00014   Revision 1.4  2004/02/11 10:19:54  verdoolaege
    00015   add const qualifier
    00016
    00017   Revision 1.3  2004/02/08 21:53:27  kienhuis
    00018   Update from Fabien Coelho, via Bart Kienhuis
    00019
    00020   I've updated here in the C3/Linear library the arithmetic_error
    00021   package that I developped (with others) to handle exceptions in C.
    00022   It adds a simple callback feature which is needed for pips here.
    00023   If you do not use it, it should not harm;-)
    00024
    00025   Revision 1.27  2003/09/04 09:40:37  coelho
    00026   init added.
    00027   verbosity mask added.
    00028
    00029   Revision 1.26  2003/09/03 14:05:20  coelho
    00030   push/pop callbacks called.
    00031
    00032   Revision 1.20  2003/08/18 09:55:09  coelho
    00033   get_exception_name added...
    00034
    00035   Revision 1.19  2003/06/13 13:59:07  coelho
    00036   const out.
    00037
    00038   Revision 1.18  2003/06/13 13:54:47  coelho
    00039   hop.
    00040
    00041   Revision 1.17  2002/04/02 08:44:54  coelho
    00042   timeout_error ajoute.
    00043
    00044   Revision 1.16  2000/10/27 13:26:03  ancourt
    00045   exception_thrown -> linear_number_of_exception_thrown
    00046
    00047   Revision 1.15  2000/07/27 15:21:55  coelho
    00048   message++
    00049
    00050   Revision 1.14  2000/07/27 14:59:59  coelho
    00051   trace added.
    00052
    00053   Revision 1.13  2000/07/26 08:41:23  coelho
    00054   the_last_just_thrown_exception management added.
    00055
    00056   Revision 1.12  1998/10/26 18:48:34  coelho
    00057   message++.
    00058
    00059   Revision 1.11  1998/10/26 14:38:06  coelho
    00060   constants back in.
    00061
    00062   Revision 1.10  1998/10/26 14:35:47  coelho
    00063   constants in .h.
    00064
    00065   Revision 1.9  1998/10/24 15:36:22  coelho
    00066   better exception error messages...
    00067
    00068   Revision 1.8  1998/10/24 15:19:17  coelho
    00069   more verbose throw...
    00070
    00071   Revision 1.7  1998/10/24 14:31:13  coelho
    00072   new stack implementation.
    00073   checks for matching catch/uncatch.
    00074   debug mode.
    00075
    00076   Revision 1.6  1998/10/24 09:31:06  coelho
    00077   RCS headers.
    00078   'const' tried.
    00079
    00080 */
    00081
    00082 #include <stdio.h>
    00083 #include <stdlib.h>
    00084 #include <string.h>
    00085
    00086 #include "arithmetique.h"
    00087
    00088 /* global constants to designate exceptions.
    00089    to be put in the type field bellow.
    00090    cproto 4.6 does not line 'const'...
    00091 */
    00092 unsigned int overflow_error = 1;
    00093 unsigned int simplex_arithmetic_error = 2;
    00094 unsigned int user_exception_error = 4;
    00095 unsigned int parser_exception_error = 8;
    00096 unsigned int timeout_error = 16;
    00097
    00098 /* catch all */
    00099 unsigned int any_exception_error = ~0;
    00100
    00101
    00102 /*
    00103  * On a few systems, type boolean and/or its values FALSE, TRUE may appear
    00104  * in standard header files.  Or you may have conflicts with application-
    00105  * specific header files that you want to include together with these files.
    00106  * Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
    00107  */
    00108
    00109 #ifndef HAVE_BOOLEAN
    00110 typedef int boolean;
    00111 #endif
    00112 #ifndef FALSE                   /* in case these macros already exist */
    00113 #define FALSE   0               /* values of boolean */
    00114 #endif
    00115 #ifndef TRUE
    00116 #define TRUE    1
    00117 #endif
    00118
    00119 const char *get_exception_name(unsigned int exception)
    00120 {
    00121   if (exception==overflow_error)
    00122     return "overflow_error exception";
    00123   if (exception==simplex_arithmetic_error)
    00124     return "simplex_arithmetic_error exception";
    00125   if (exception==user_exception_error)
    00126     return "user_exception_error exception";
    00127   if (exception==parser_exception_error)
    00128     return "parser_exception_error exception";
    00129   if (exception==timeout_error)
    00130     return "timeout_error exception";
    00131   if (exception==any_exception_error)
    00132     return "all exceptions mask";
    00133
    00134   return "unknown or mixed exception";
    00135 }
    00136
    00137 /* keep track of last thrown exception for RETHROW()
    00138  */
    00139 unsigned int the_last_just_thrown_exception = 0;
    00140
    00141 /* whether to run in debug mode (that is to trace catch/uncatch/throw)
    00142  */
    00143 static int linear_exception_debug_mode = FALSE;
    00144 static unsigned int linear_exception_verbose = 1 | 2 | 16 ;
    00145
    00146 /* A structure for the exception stack.
    00147  */
    00148 typedef struct
    00149 {
    00150   /* exception type.
    00151    */
    00152   int what;
    00153
    00154   /* where to jump to.
    00155    */
    00156   jmp_buf where;
    00157
    00158   /* location of the CATCH to be matched against the UNCATCH.
    00159    */
    00160   const char * function;
    00161   const char * file;
    00162   int    line;
    00163 }
    00164   linear_exception_holder;
    00165
    00166 /* exception stack.
    00167    maximum extension.
    00168    current index (next available bucket)
    00169  */
    00170 #define MAX_STACKED_CONTEXTS 64
    00171 static linear_exception_holder exception_stack[MAX_STACKED_CONTEXTS];
    00172 static int exception_index = 0;
    00173
    00174 /* callbacks...
    00175  */
    00176 static exception_callback_t push_callback = NULL;
    00177 static exception_callback_t pop_callback = NULL;
    00178
    00179 void set_exception_callbacks(exception_callback_t push,
    00180                              exception_callback_t pop)
    00181 {
    00182   if (push_callback!=NULL || pop_callback!=NULL)
    00183   {
    00184     fprintf(stderr, "exception callbacks already defined! (%p, %p)\n",
    00185             push_callback, pop_callback);
    00186     abort();
    00187   }
    00188
    00189   push_callback = push;
    00190   pop_callback = pop;
    00191 }
    00192
    00193 /* total number of exceptions thrown, for statistics.
    00194  */
    00195 int linear_number_of_exception_thrown = 0;
    00196
    00197 /* dump stack
    00198  */
    00199 void dump_exception_stack_to_file(FILE * f)
    00200 {
    00201   int i;
    00202   fprintf(f, "[dump_exception_stack_to_file] size=%d\n", exception_index);
    00203   for (i=0; i<exception_index; i++)
    00204   {
    00205     fprintf(f,
    00206             "%d: [%s:%d in %s (%d)]\n",
    00207             i,
    00208             exception_stack[i].file,
    00209             exception_stack[i].line,
    00210             exception_stack[i].function,
    00211             exception_stack[i].what);
    00212   }
    00213   fprintf(f, "\n");
    00214 }
    00215
    00216 void dump_exception_stack()
    00217 {
    00218   dump_exception_stack_to_file(stderr);
    00219 }
    00220
    00221 #define exception_debug_message(type)                             \
    00222     fprintf(stderr, "%s[%s:%d %s (%d)/%d]\n",                     \
    00223             type, file, line, function, what, exception_index)
    00224
    00225 #define exception_debug_trace(type) \
    00226     if (linear_exception_debug_mode) { exception_debug_message(type); }
    00227
    00228
    00229 /* push a what exception on stack.
    00230  */
    00231 jmp_buf *
    00232 push_exception_on_stack(
    00233     int what,
    00234     const char * function,
    00235     const char * file,
    00236     int line)
    00237 {
    00238   exception_debug_trace("PUSH ");
    00239
    00240   if (exception_index==MAX_STACKED_CONTEXTS)
    00241   {
    00242     exception_debug_message("push");
    00243     fprintf(stderr, "exception stack overflow\n");
    00244     dump_exception_stack();
    00245     abort();
    00246   }
    00247
    00248   if (push_callback) push_callback(file, function, line);
    00249
    00250   the_last_just_thrown_exception = 0;
    00251
    00252   exception_stack[exception_index].what = what;
    00253   exception_stack[exception_index].function = function;
    00254   exception_stack[exception_index].file = file;
    00255   exception_stack[exception_index].line = line;
    00256
    00257   return & exception_stack[exception_index++].where;
    00258 }
    00259
    00260 #if !defined(same_string_p)
    00261 #define same_string_p(s1, s2) (strcmp((s1),(s2))==0)
    00262 #endif
    00263
    00264 /* pop a what exception.
    00265    check for any mismatch!
    00266  */
    00267 void
    00268 pop_exception_from_stack(
    00269     int what,
    00270     const char * function,
    00271     const char * file,
    00272     int line)
    00273 {
    00274   exception_debug_trace("POP  ");
    00275
    00276   if (exception_index==0)
    00277   {
    00278     exception_debug_message("pop");
    00279     fprintf(stderr, "exception stack underflow\n");
    00280     dump_exception_stack();
    00281     abort();
    00282   }
    00283
    00284   if (pop_callback) pop_callback(file, function, line);
    00285
    00286   exception_index--;
    00287   the_last_just_thrown_exception = 0;
    00288
    00289   if ((exception_stack[exception_index].what != what) ||
    00290       !same_string_p(exception_stack[exception_index].file, file) ||
    00291       !same_string_p(exception_stack[exception_index].function, function))
    00292   {
    00293     exception_debug_message("pop");
    00294     fprintf(stderr,
    00295             "exception stack mismatch at depth=%d:\n"
    00296             "   CATCH: %s:%d in %s (%d)\n"
    00297             " UNCATCH: %s:%d in %s (%d)\n",
    00298             exception_index,
    00299             exception_stack[exception_index].file,
    00300             exception_stack[exception_index].line,
    00301             exception_stack[exception_index].function,
    00302             exception_stack[exception_index].what,
    00303             file, line, function, what);
    00304     dump_exception_stack();
    00305     abort();
    00306   }
    00307 }
    00308
    00309 /* throws an exception of a given type by searching for
    00310    the specified 'what' in the current exception stack.
    00311 */
    00312 void throw_exception(
    00313     int what,
    00314     const char * function,
    00315     const char * file,
    00316     int line)
    00317 {
    00318   int i;
    00319
    00320   exception_debug_trace("THROW");
    00321
    00322   the_last_just_thrown_exception = what; /* for rethrow */
    00323
    00324   for (i=exception_index-1; i>=0; i--)
    00325   {
    00326     if (pop_callback)
    00327       /* pop with push parameters! */
    00328       pop_callback(exception_stack[i].file,
    00329                    exception_stack[i].function,
    00330                    exception_stack[i].line);
    00331
    00332     if (exception_stack[i].what & what)
    00333     {
    00334       exception_index = i;
    00335       linear_number_of_exception_thrown++;
    00336
    00337       if (linear_exception_debug_mode)
    00338         fprintf(stderr, "---->[%s:%d %s (%d)/%d]\n",
    00339                 exception_stack[i].file,
    00340                 exception_stack[i].line,
    00341                 exception_stack[i].function,
    00342                 exception_stack[i].what,
    00343                 i);
    00344
    00345       /* trace some exceptions... */
    00346       if (linear_exception_verbose & what)
    00347         fprintf(stderr, "exception %d/%d: %s(%s:%d) -> %s(%s:%d)\n",
    00348                 what, exception_stack[i].what,
    00349                 function, file, line,
    00350                 exception_stack[i].function,
    00351                 exception_stack[i].file,
    00352                 exception_stack[i].line);
    00353
    00354       longjmp(exception_stack[i].where, 0);
    00355     }
    00356   }
    00357
    00358   /* error. */
    00359   exception_debug_message("throw");
    00360   fprintf(stderr,
    00361           "exception not found in stack:\n"
    00362           "an exception was THROWN without a proper matching CATCH\n");
    00363   dump_exception_stack();
    00364   abort();
    00365 }
    00366
    00367 void linear_initialize_exception_stack(
    00368   unsigned int verbose_exceptions,
    00369   exception_callback_t push,
    00370   exception_callback_t pop)
    00371 {
    00372   linear_exception_verbose = verbose_exceptions;
    00373   set_exception_callbacks(push, pop);
    00374 }