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

pike_error.h

Go to the documentation of this file.
00001 /*
00002 || This file is part of Pike. For copyright information see COPYRIGHT.
00003 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
00004 || for more information.
00005 || $Id: pike_error.h,v 1.36 2004/11/14 17:44:05 mast Exp $
00006 */
00007 
00008 #ifndef PIKE_ERROR_H
00009 #define PIKE_ERROR_H
00010 
00011 #include <stdarg.h>
00012 
00013 #ifdef CONFIGURE_TEST
00014 
00015 #include <stdio.h>
00016 
00017 static inline void Pike_fatal (const char *fmt, ...)
00018 {
00019   va_list args;
00020   va_start (args, fmt);
00021   vfprintf (stderr, fmt, args);
00022   abort();
00023 }
00024 
00025 #define Pike_error Pike_fatal
00026 
00027 #else  /* !CONFIGURE_TEST */
00028 
00029 #include "machine.h"
00030 
00031 #ifdef HAVE_SETJMP_H
00032 #include <setjmp.h>
00033 #undef HAVE_SETJMP_H
00034 #endif
00035 
00036 #if defined(HAVE_SIGSETJMP) && defined(HAVE_SIGLONGJMP)
00037 #define HAVE_AND_USE_SIGSETJMP
00038 #define LOW_JMP_BUF             sigjmp_buf
00039 #define LOW_SETJMP(X)           sigsetjmp(X, 0)
00040 #define LOW_LONGJMP(X, Y)       siglongjmp(X, Y)
00041 #elif defined(HAVE__SETJMP) && defined(HAVE__LONGJMP)
00042 #define HAVE_AND_USE__SETJMP
00043 #define LOW_JMP_BUF             jmp_buf
00044 #define LOW_SETJMP(X)           _setjmp(X)
00045 #define LOW_LONGJMP(X, Y)       _longjmp(X, Y)
00046 #else
00047 /* Assume we have setjmp and longjmp, they are after all defined by ANSI C. */
00048 #define HAVE_AND_USE_SETJMP
00049 #define LOW_JMP_BUF             jmp_buf
00050 #define LOW_SETJMP(X)           setjmp(X)
00051 #define LOW_LONGJMP(X, Y)       longjmp(X, Y)
00052 #endif
00053 
00054 #if 1
00055 PMOD_EXPORT extern const char msg_fatal_error[];
00056 #define Pike_fatal \
00057  (fprintf(stderr,msg_fatal_error,__FILE__,__LINE__),debug_fatal)
00058 #else
00059 /* This is useful when debugging assembler code sometimes... -Hubbe */
00060 #define Pike_fatal \
00061  (fprintf(stderr,"%s: Fatal error:\n",__FILE__ ":" DEFINETOSTR(__LINE__) ),debug_fatal)
00062 #endif
00063 
00064 #ifndef NO_PIKE_SHORTHAND
00065 #define fatal Pike_fatal
00066 #endif
00067 
00068 PMOD_EXPORT DECLSPEC(noreturn) void debug_fatal(const char *fmt, ...) ATTRIBUTE((noreturn));
00069 
00070 
00071 #include "svalue.h"
00072 
00073 
00074 typedef void (*error_call)(void *);
00075 
00076 #ifndef STRUCT_FRAME_DECLARED
00077 #define STRUCT_FRAME_DECLARED
00078 struct pike_frame;
00079 #endif
00080 
00081 #define THROW_ERROR 10
00082 #define THROW_THREAD_EXIT 20
00083 #define THROW_THREAD_KILLED 30
00084 #define THROW_EXIT 40
00085 #define THROW_MAX_SEVERITY 100
00086 
00087 /* #define ONERROR_DEBUG */
00088 
00089 #ifdef ONERROR_DEBUG
00090 #define OED_FPRINTF(X)  fprintf X
00091 #else /* !ONERROR_DEBUG */
00092 #define OED_FPRINTF(X)
00093 #endif /* ONERROR_DEBUG */
00094 
00095 typedef struct ONERROR
00096 {
00097   struct ONERROR *previous;
00098   error_call func;
00099   void *arg;
00100 #ifdef PIKE_DEBUG
00101   const char *file;
00102   int line;
00103 #endif /* PIKE_DEBUG */
00104 } ONERROR;
00105 
00106 typedef struct JMP_BUF
00107 {
00108   struct JMP_BUF *previous;
00109   LOW_JMP_BUF recovery;
00110   struct pike_frame *frame_pointer;
00111   ptrdiff_t stack_pointer;
00112   ptrdiff_t mark_sp;
00113   INT32 severity;
00114   ONERROR *onerror;
00115 #ifdef PIKE_DEBUG
00116   int line;
00117   char *file;
00118 #endif
00119 } JMP_BUF;
00120 
00121 PMOD_EXPORT extern struct svalue throw_value;
00122 extern int throw_severity;
00123 
00124 #ifdef PIKE_DEBUG
00125 PMOD_EXPORT extern const char msg_unsetjmp_nosync_1[];
00126 PMOD_EXPORT extern const char msg_unsetjmp_nosync_2[];
00127 #define UNSETJMP(X) do{ \
00128    check_recovery_context(); \
00129    OED_FPRINTF((stderr, "unsetjmp(%p) %s:%d\n", \
00130                 &(X),  __FILE__, __LINE__)); \
00131   if(Pike_interpreter.recoveries != &X) { \
00132     if(Pike_interpreter.recoveries) \
00133       Pike_fatal(msg_unsetjmp_nosync_1,Pike_interpreter.recoveries->file); \
00134     else \
00135       Pike_fatal(msg_unsetjmp_nosync_2); \
00136     } \
00137     Pike_interpreter.recoveries=X.previous; \
00138    check_recovery_context(); \
00139   }while (0)
00140 
00141 #ifdef DMALLOC_LOCATION
00142 #define PERR_LOCATION() DMALLOC_LOCATION()
00143 #else
00144 #define PERR_LOCATION() ( __FILE__ ":" DEFINETOSTR(__LINE__) )
00145 #endif
00146 
00147 #define DEBUG_LINE_ARGS ,char *location
00148 #define SETJMP(X) LOW_SETJMP((init_recovery(&X, 0, PERR_LOCATION())->recovery))
00149 #define SETJMP_SP(jmp, stack_pop_levels)                                \
00150   LOW_SETJMP((init_recovery(&jmp, stack_pop_levels, PERR_LOCATION())->recovery))
00151 #else
00152 #define DEBUG_LINE_ARGS 
00153 #define SETJMP(X) LOW_SETJMP((init_recovery(&X, 0)->recovery))
00154 #define SETJMP_SP(jmp, stack_pop_levels)                                \
00155   LOW_SETJMP((init_recovery(&jmp, stack_pop_levels)->recovery))
00156 #define UNSETJMP(X) Pike_interpreter.recoveries=X.previous
00157 #endif
00158 
00159 
00160 #ifdef PIKE_DEBUG
00161 #define SET_ONERROR(X,Y,Z) \
00162   do{ \
00163      check_recovery_context(); \
00164      OED_FPRINTF((stderr, "SET_ONERROR(%p, %p, %p) %s:%d\n", \
00165                   &(X), (Y), (void *)(Z), __FILE__, __LINE__)); \
00166      X.func=(error_call)(Y); \
00167      DO_IF_DMALLOC( if( X.func == free ) X.func=dmalloc_free;) \
00168      X.arg=(void *)(Z); \
00169      if(!Pike_interpreter.recoveries) break; \
00170      X.previous=Pike_interpreter.recoveries->onerror; \
00171      X.file = __FILE__; \
00172      X.line = __LINE__; \
00173      Pike_interpreter.recoveries->onerror=&X; \
00174   }while(0)
00175 
00176 PMOD_EXPORT extern const char msg_last_setjmp[];
00177 PMOD_EXPORT extern const char msg_unset_onerr_nosync_1[];
00178 PMOD_EXPORT extern const char msg_unset_onerr_nosync_2[];
00179 #define UNSET_ONERROR(X) do {\
00180     check_recovery_context(); \
00181     OED_FPRINTF((stderr, "UNSET_ONERROR(%p) %s:%d\n", \
00182                  &(X), __FILE__, __LINE__)); \
00183     if(!Pike_interpreter.recoveries) break; \
00184     if(Pike_interpreter.recoveries->onerror != &(X)) { \
00185       fprintf(stderr,msg_last_setjmp,Pike_interpreter.recoveries->file); \
00186       if (Pike_interpreter.recoveries->onerror) { \
00187         Pike_fatal(msg_unset_onerr_nosync_1,\
00188                    Pike_interpreter.recoveries->onerror, &(X), \
00189                    Pike_interpreter.recoveries->onerror->file); \
00190       } else { \
00191         Pike_fatal(msg_unset_onerr_nosync_2); \
00192       } \
00193     } \
00194     Pike_interpreter.recoveries->onerror=(X).previous; \
00195   } while(0)
00196 
00197 PMOD_EXPORT extern const char msg_assert_onerr[];
00198 #define ASSERT_ONERROR(X) \
00199   do{ \
00200     if (!Pike_interpreter.recoveries) break; \
00201     if (Pike_interpreter.recoveries->onerror != &X) { \
00202       Pike_fatal(msg_assert_onerr, \
00203                  __FILE__, __LINE__, &(X)); \
00204     } \
00205   }while(0)
00206 #else /* !PIKE_DEBUG */
00207 #define SET_ONERROR(X,Y,Z) \
00208   do{ \
00209      X.func=(error_call)(Y); \
00210      X.arg=(void *)(Z); \
00211      if(!Pike_interpreter.recoveries) break; \
00212      X.previous=Pike_interpreter.recoveries->onerror; \
00213      Pike_interpreter.recoveries->onerror=&X; \
00214   }while(0)
00215 
00216 #define UNSET_ONERROR(X) Pike_interpreter.recoveries && (Pike_interpreter.recoveries->onerror=X.previous)
00217 
00218 #define ASSERT_ONERROR(X)
00219 #endif /* PIKE_DEBUG */
00220 
00221 #define CALL_AND_UNSET_ONERROR(X) do {          \
00222      X.func(X.arg);                             \
00223      UNSET_ONERROR(X);                          \
00224   }while(0)
00225 
00226 #if defined(PIKE_DEBUG) && 0
00227 /* Works, but probably not interresting for most people
00228  *      /grubba 1998-04-11
00229  */
00230 #define PIKE_ERROR(NAME, TEXT, SP, ARGS) new_error(NAME, TEXT, SP, ARGS, __FILE__, __LINE__)
00231 #else
00232 #define PIKE_ERROR(NAME, TEXT, SP, ARGS) new_error(NAME, TEXT, SP, ARGS, NULL, 0)
00233 #endif /* PIKE_DEBUG */
00234 
00235 /* Prototypes begin here */
00236 PMOD_EXPORT void check_recovery_context(void);
00237 PMOD_EXPORT void pike_gdb_breakpoint(INT32 args);
00238 PMOD_EXPORT JMP_BUF *init_recovery(JMP_BUF *r, size_t stack_pop_levels DEBUG_LINE_ARGS);
00239 PMOD_EXPORT DECLSPEC(noreturn) void pike_throw(void) ATTRIBUTE((noreturn));
00240 PMOD_EXPORT void push_error(const char *description);
00241 PMOD_EXPORT DECLSPEC(noreturn) void low_error(const char *buf) ATTRIBUTE((noreturn));
00242 PMOD_EXPORT void Pike_vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
00243 void DECLSPEC(noreturn) va_error(const char *fmt, va_list args) ATTRIBUTE((noreturn));
00244 PMOD_EXPORT DECLSPEC(noreturn) void new_error(const char *name, const char *text, struct svalue *oldsp,
00245                INT32 args, const char *file, int line) ATTRIBUTE((noreturn));
00246 PMOD_EXPORT void exit_on_error(const void *msg);
00247 PMOD_EXPORT void fatal_on_error(const void *msg);
00248 PMOD_EXPORT DECLSPEC(noreturn) void Pike_error(const char *fmt,...) ATTRIBUTE((noreturn));
00249 PMOD_EXPORT DECLSPEC(noreturn) void debug_fatal(const char *fmt, ...) ATTRIBUTE((noreturn));
00250 void DECLSPEC(noreturn) generic_error_va(struct object *o,
00251                       const char *func,
00252                       struct svalue *base_sp,  int args,
00253                       const char *fmt,
00254                       va_list foo)
00255   ATTRIBUTE((noreturn));
00256 PMOD_EXPORT DECLSPEC(noreturn) void throw_error_object(
00257   struct object *o,
00258   const char *func,
00259   struct svalue *base_sp,  int args,
00260   const char *desc, ...) ATTRIBUTE((noreturn));
00261 PMOD_EXPORT void DECLSPEC(noreturn) generic_error(
00262   const char *func,
00263   struct svalue *base_sp,  int args,
00264   const char *desc, ...) ATTRIBUTE((noreturn));
00265 PMOD_EXPORT DECLSPEC(noreturn) void index_error(
00266   const char *func,
00267   struct svalue *base_sp,  int args,
00268   struct svalue *val,
00269   struct svalue *ind,
00270   const char *desc, ...) ATTRIBUTE((noreturn));
00271 PMOD_EXPORT DECLSPEC(noreturn) void bad_arg_error(
00272   const char *func,
00273   struct svalue *base_sp,  int args,
00274   int which_arg,
00275   const char *expected_type,
00276   struct svalue *got,
00277   const char *desc, ...)  ATTRIBUTE((noreturn));
00278 PMOD_EXPORT void DECLSPEC(noreturn) math_error(
00279   const char *func,
00280   struct svalue *base_sp,  int args,
00281   struct svalue *number,
00282   const char *desc, ...) ATTRIBUTE((noreturn));
00283 PMOD_EXPORT void DECLSPEC(noreturn) resource_error(
00284   const char *func,
00285   struct svalue *base_sp,  int args,
00286   const char *resource_type,
00287   size_t howmuch,
00288   const char *desc, ...) ATTRIBUTE((noreturn));
00289 PMOD_EXPORT void DECLSPEC(noreturn) permission_error(
00290   const char *func,
00291   struct svalue *base_sp, int args,
00292   const char *permission_type,
00293   const char *desc, ...) ATTRIBUTE((noreturn));
00294 PMOD_EXPORT void wrong_number_of_args_error(const char *name, int args, int expected)
00295   ATTRIBUTE((noreturn));
00296 void init_error(void);
00297 void cleanup_error(void);
00298 /* Prototypes end here */
00299 
00300 /* Some useful error macros. */
00301 
00302 
00303 /* This one should be used when the type of the argument is wrong. */
00304 PMOD_EXPORT extern const char msg_bad_arg[];
00305 #define SIMPLE_ARG_TYPE_ERROR(FUNC, ARG, EXPECT) \
00306    bad_arg_error(FUNC, Pike_sp-args, args, ARG, EXPECT, Pike_sp+ARG-1-args,\
00307                  msg_bad_arg, ARG, FUNC, EXPECT)
00308 /* Less descriptive macro name kept for compatibility. */
00309 #define SIMPLE_BAD_ARG_ERROR(FUNC, ARG, EXPECT) \
00310    bad_arg_error(FUNC, Pike_sp-args, args, ARG, EXPECT, Pike_sp+ARG-1-args,\
00311                  msg_bad_arg, ARG, FUNC, EXPECT)
00312 
00313 /* This one should be used when there's some problem with the argument
00314  * other than a bogus type. PROBLEM is a full sentence without a
00315  * trailing newline. */
00316 PMOD_EXPORT extern const char msg_bad_arg_2[];
00317 #define SIMPLE_ARG_ERROR(FUNC, ARG, PROBLEM) \
00318   bad_arg_error (FUNC, Pike_sp-args, args, ARG, NULL, Pike_sp+ARG-1-args, \
00319                  msg_bad_arg_2, ARG, FUNC, PROBLEM)
00320 
00321 #define SIMPLE_WRONG_NUM_ARGS_ERROR(FUNC, ARG) \
00322   wrong_number_of_args_error (FUNC, args, ARG)
00323 /* The following is for compatibility. */
00324 #define SIMPLE_TOO_FEW_ARGS_ERROR(FUNC, ARG) \
00325   wrong_number_of_args_error (FUNC, args, ARG)
00326 
00327 PMOD_EXPORT extern const char msg_out_of_mem[];
00328 #define SIMPLE_OUT_OF_MEMORY_ERROR(FUNC, AMOUNT) \
00329    resource_error(FUNC, Pike_sp-args, args, "memory", AMOUNT, msg_out_of_mem)
00330 
00331 PMOD_EXPORT extern const char msg_div_by_zero[];
00332 #define SIMPLE_DIVISION_BY_ZERO_ERROR(FUNC) \
00333      math_error(FUNC, Pike_sp-args, args, 0, msg_div_by_zero)
00334 
00335 #ifndef PIKE_DEBUG
00336 #define check_recovery_context() ((void)0)
00337 #endif
00338 
00339 /* Experimental convenience exception macros. */
00340 
00341 #define exception_try \
00342         do \
00343         { \
00344             int __exception_rethrow, __is_exception; \
00345             JMP_BUF exception; \
00346             __is_exception = SETJMP(exception); \
00347             __exception_rethrow = 0; \
00348             if(__is_exception) /* rethrow needs this */ \
00349                 UNSETJMP(exception); \
00350             if(!__is_exception)
00351     
00352 #define exception_catch_if \
00353             else if
00354 
00355 #define exception_catch(e) \
00356             exception_catch_if(exception->severity = (e))
00357 
00358 #define exception_catch_all \
00359             exception_catch_if(1)
00360 
00361 #define exception_semicatch_all \
00362             exception_catch_if((__exception_rethrow = 1))
00363 
00364 #define rethrow \
00365             pike_throw()
00366 
00367 #define exception_endtry \
00368             else \
00369                 __exception_rethrow = 1; \
00370             if(__is_exception) { \
00371                 free_svalue(&throw_value); \
00372                 throw_value.type = T_INT; \
00373             } \
00374             else \
00375                 UNSETJMP(exception); \
00376             if(__exception_rethrow) \
00377                 rethrow; \
00378         } \
00379         while(0)
00380 
00381 /* Generic error stuff */
00382 #define ERR_EXT_DECLARE
00383 #include "errors.h"
00384 
00385 #endif  /* !CONFIGURE_TEST */
00386 
00387 #endif /* PIKE_ERROR_H */

Generated on Fri Jul 22 23:44:26 2005 for Pike by  doxygen 1.3.9.1