00001
00002
00003
00004
00005
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
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
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
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
00088
00089 #ifdef ONERROR_DEBUG
00090 #define OED_FPRINTF(X) fprintf X
00091 #else
00092 #define OED_FPRINTF(X)
00093 #endif
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
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
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
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
00228
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
00234
00235
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
00299
00300
00301
00302
00303
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
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
00314
00315
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
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
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) \
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
00382 #define ERR_EXT_DECLARE
00383 #include "errors.h"
00384
00385 #endif
00386
00387 #endif