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.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 }

Generated on Thu Sep 4 15:28:57 2008 for polylib by doxygen 1.3.5