Main Page | Class List | File List | Class Members | File Members

errors.c

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

Generated on Mon Sep 12 14:48:28 2005 for polylib by doxygen 1.3.5