Main Page   Compound List   File List   Compound Members   File Members  

errors.c

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

Generated on Mon Mar 15 10:59:50 2004 for polylib by doxygen1.2.18