cb22561995-10-11Fredrik Hübinette (Hubbe) /*\
06983f1996-09-22Fredrik Hübinette (Hubbe) ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License)
cb22561995-10-11Fredrik Hübinette (Hubbe) ||| See the files COPYING and DISCLAIMER for more information. \*/
24ddc71998-03-28Henrik Grubbström (Grubba)  /*
0236db2000-12-04Fredrik Hübinette (Hubbe)  * $Id: error.h,v 1.41 2000/12/05 03:26:10 hubbe Exp $
24ddc71998-03-28Henrik Grubbström (Grubba)  */
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifndef ERROR_H #define ERROR_H
2d31fb1996-08-12Fredrik Hübinette (Hubbe) #include "machine.h" #ifdef HAVE_SETJMP_H
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <setjmp.h>
2d31fb1996-08-12Fredrik Hübinette (Hubbe) #undef HAVE_SETJMP_H #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <stdarg.h>
2d31fb1996-08-12Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "svalue.h"
cb22561995-10-11Fredrik Hübinette (Hubbe) typedef void (*error_call)(void *);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
dfa5b31996-12-05Fredrik Hübinette (Hubbe) #ifndef STRUCT_FRAME_DECLARED #define STRUCT_FRAME_DECLARED
4218011999-01-31Fredrik Hübinette (Hubbe) struct pike_frame;
dfa5b31996-12-05Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
24dd881998-01-27Fredrik Hübinette (Hubbe) #define THROW_ERROR 10 #define THROW_THREAD_EXIT 20 #define THROW_THREAD_KILLED 30 #define THROW_EXIT 40 #define THROW_MAX_SEVERITY 100
61e9a01998-01-25Fredrik Hübinette (Hubbe) 
c857761999-03-16Fredrik Hübinette (Hubbe) /* #define ONERROR_DEBUG */
8e8b9f1998-07-17Henrik Grubbström (Grubba) #ifdef ONERROR_DEBUG #define OED_FPRINTF(X) fprintf X #else /* !ONERROR_DEBUG */ #define OED_FPRINTF(X) #endif /* ONERROR_DEBUG */
cb22561995-10-11Fredrik Hübinette (Hubbe) typedef struct ONERROR { struct ONERROR *previous;
cbf3d42000-02-07Fredrik Hübinette (Hubbe)  error_call func; void *arg;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
0abfe01998-07-13Henrik Grubbström (Grubba)  const char *file; int line;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #endif /* PIKE_DEBUG */
cb22561995-10-11Fredrik Hübinette (Hubbe) } ONERROR;
5267b71995-08-09Fredrik Hübinette (Hubbe) typedef struct JMP_BUF { struct JMP_BUF *previous;
e9f9141996-09-29Fredrik Hübinette (Hubbe)  jmp_buf recovery;
a2ad152000-02-16Fredrik Hübinette (Hubbe)  struct pike_frame *Pike_fp; INT32 Pike_sp; INT32 Pike_mark_sp;
61e9a01998-01-25Fredrik Hübinette (Hubbe)  INT32 severity;
cb22561995-10-11Fredrik Hübinette (Hubbe)  ONERROR *onerror;
cbf3d42000-02-07Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG int line; char *file; #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) } JMP_BUF; extern JMP_BUF *recoveries; extern struct svalue throw_value;
61e9a01998-01-25Fredrik Hübinette (Hubbe) extern int throw_severity;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5196c51998-07-16Fredrik Hübinette (Hubbe) #define UNSETJMP(X) do{ \
c857761999-03-16Fredrik Hübinette (Hubbe)  check_recovery_context(); \ OED_FPRINTF((stderr, "unsetjmp(%p) %s:%d\n", \ &(X), __FILE__, __LINE__)); \
5196c51998-07-16Fredrik Hübinette (Hubbe)  if(recoveries != &X) { \ if(recoveries) \ fatal("UNSETJMP out of sync! (last SETJMP at %s:%d)!\n",recoveries->file,recoveries->line); \ else \ fatal("UNSETJMP out of sync! (recoveries = 0)\n"); \ } \ recoveries=X.previous; \
c857761999-03-16Fredrik Hübinette (Hubbe)  check_recovery_context(); \
5196c51998-07-16Fredrik Hübinette (Hubbe)  }while (0) #define DEBUG_LINE_ARGS ,int line, char *file #define SETJMP(X) setjmp((init_recovery(&X,__LINE__,__FILE__)->recovery)) #else #define DEBUG_LINE_ARGS
e9f9141996-09-29Fredrik Hübinette (Hubbe) #define SETJMP(X) setjmp((init_recovery(&X)->recovery))
c857761999-03-16Fredrik Hübinette (Hubbe) #define UNSETJMP(X) recoveries=X.previous
5196c51998-07-16Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
cb22561995-10-11Fredrik Hübinette (Hubbe) #define SET_ONERROR(X,Y,Z) \ do{ \
c857761999-03-16Fredrik Hübinette (Hubbe)  check_recovery_context(); \
8e8b9f1998-07-17Henrik Grubbström (Grubba)  OED_FPRINTF((stderr, "SET_ONERROR(%p, %p, %p) %s:%d\n", \
65b0bd1999-03-17Henrik Grubbström (Grubba)  &(X), (Y), (void *)(Z), __FILE__, __LINE__)); \
cb22561995-10-11Fredrik Hübinette (Hubbe)  X.func=(error_call)(Y); \
424d9c1999-05-02Fredrik Hübinette (Hubbe)  DO_IF_DMALLOC( if( X.func == free ) X.func=dmalloc_free;) \
cb22561995-10-11Fredrik Hübinette (Hubbe)  X.arg=(void *)(Z); \
7e97c31999-01-21Fredrik Hübinette (Hubbe)  if(!recoveries) break; \
07513e1996-10-04Fredrik Hübinette (Hubbe)  X.previous=recoveries->onerror; \
0abfe01998-07-13Henrik Grubbström (Grubba)  X.file = __FILE__; \ X.line = __LINE__; \
07513e1996-10-04Fredrik Hübinette (Hubbe)  recoveries->onerror=&X; \
cb22561995-10-11Fredrik Hübinette (Hubbe)  }while(0)
9dd1f91997-10-07Fredrik Hübinette (Hubbe) #define UNSET_ONERROR(X) do {\
c857761999-03-16Fredrik Hübinette (Hubbe)  check_recovery_context(); \
8e8b9f1998-07-17Henrik Grubbström (Grubba)  OED_FPRINTF((stderr, "UNSET_ONERROR(%p) %s:%d\n", \ &(X), __FILE__, __LINE__)); \
0abfe01998-07-13Henrik Grubbström (Grubba)  if(!recoveries) break; \ if(recoveries->onerror != &(X)) { \
5196c51998-07-16Fredrik Hübinette (Hubbe)  fprintf(stderr,"LAST SETJMP: %s:%d\n",recoveries->file,recoveries->line); \
0abfe01998-07-13Henrik Grubbström (Grubba)  if (recoveries->onerror) { \
c857761999-03-16Fredrik Hübinette (Hubbe)  fatal("UNSET_ONERROR out of sync (%p != %p).\n" \ "Last SET_ONERROR is from %s:%d\n",\ recoveries->onerror, &(X), \
0abfe01998-07-13Henrik Grubbström (Grubba)  recoveries->onerror->file, recoveries->onerror->line ); \ } else { \
9435371998-07-16Henrik Grubbström (Grubba)  fatal("UNSET_ONERROR out of sync. No recoveries left.\n"); \
0abfe01998-07-13Henrik Grubbström (Grubba)  } \ } \ recoveries->onerror=(X).previous; \
9dd1f91997-10-07Fredrik Hübinette (Hubbe)  } while(0)
56d6c41998-07-17Henrik Grubbström (Grubba)  #define ASSERT_ONERROR(X) \ do{ \ if (!recoveries) break; \ if (recoveries->onerror != &X) { \ fatal("%s:%d ASSERT_ONERROR(%p) failed\n", \ __FILE__, __LINE__, &(X)); \ } \ }while(0)
71f3a21998-11-22Fredrik Hübinette (Hubbe) #else /* !PIKE_DEBUG */
0abfe01998-07-13Henrik Grubbström (Grubba) #define SET_ONERROR(X,Y,Z) \ do{ \ X.func=(error_call)(Y); \ X.arg=(void *)(Z); \
cbf3d42000-02-07Fredrik Hübinette (Hubbe)  if(!recoveries) break; \
0abfe01998-07-13Henrik Grubbström (Grubba)  X.previous=recoveries->onerror; \ recoveries->onerror=&X; \ }while(0)
eb8c3e1998-02-24Fredrik Hübinette (Hubbe) #define UNSET_ONERROR(X) recoveries && (recoveries->onerror=X.previous)
56d6c41998-07-17Henrik Grubbström (Grubba)  #define ASSERT_ONERROR(X)
71f3a21998-11-22Fredrik Hübinette (Hubbe) #endif /* PIKE_DEBUG */
cb22561995-10-11Fredrik Hübinette (Hubbe) 
368f941999-08-06Henrik Grubbström (Grubba) #define CALL_AND_UNSET_ONERROR(X) do { \ X.func(X.arg); \ UNSET_ONERROR(X); \ }while(0)
71f3a21998-11-22Fredrik Hübinette (Hubbe) #if defined(PIKE_DEBUG) && 0
d8d2521998-04-11Henrik Grubbström (Grubba) /* Works, but probably not interresting for most people * /grubba 1998-04-11 */
aa366d1998-04-16Fredrik Hübinette (Hubbe) #define PIKE_ERROR(NAME, TEXT, SP, ARGS) new_error(NAME, TEXT, SP, ARGS, __FILE__, __LINE__);
0ca9f41998-04-10Henrik Grubbström (Grubba) #else
aa366d1998-04-16Fredrik Hübinette (Hubbe) #define PIKE_ERROR(NAME, TEXT, SP, ARGS) new_error(NAME, TEXT, SP, ARGS, NULL, 0);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #endif /* PIKE_DEBUG */
0ca9f41998-04-10Henrik Grubbström (Grubba) 
e9f9141996-09-29Fredrik Hübinette (Hubbe) /* Prototypes begin here */
c857761999-03-16Fredrik Hübinette (Hubbe) void check_recovery_context(void);
5196c51998-07-16Fredrik Hübinette (Hubbe) JMP_BUF *init_recovery(JMP_BUF *r DEBUG_LINE_ARGS);
dc7cc91998-01-14Fredrik Hübinette (Hubbe) void pike_throw(void) ATTRIBUTE((noreturn));
c857761999-03-16Fredrik Hübinette (Hubbe) void push_error(char *description);
f4d9e71999-10-06Henrik Grubbström (Grubba) void low_error(char *buf) ATTRIBUTE((noreturn));
4406cf1998-04-13Henrik Grubbström (Grubba) void va_error(const char *fmt, va_list args) ATTRIBUTE((noreturn));
c857761999-03-16Fredrik Hübinette (Hubbe) void new_error(const char *name, const char *text, struct svalue *oldsp, INT32 args, const char *file, int line) ATTRIBUTE((noreturn));
dceabb1996-10-09Fredrik Hübinette (Hubbe) void exit_on_error(void *msg); void fatal_on_error(void *msg);
4406cf1998-04-13Henrik Grubbström (Grubba) void error(const char *fmt,...) ATTRIBUTE((noreturn,format (printf, 1, 2))); void debug_fatal(const char *fmt, ...) ATTRIBUTE((noreturn,format (printf, 1, 2)));
81299f1999-03-19Fredrik Hübinette (Hubbe) void f_error_cast(INT32 args); void f_error_index(INT32 args); void f_error_describe(INT32 args); void f_error_backtrace(INT32 args); void generic_error_va(struct object *o, char *func, struct svalue *base_sp, int args, char *fmt, va_list foo) ATTRIBUTE((noreturn)); void generic_error( char *func, struct svalue *base_sp, int args, char *desc, ...) ATTRIBUTE((noreturn,format (printf, 4, 5))); void index_error( char *func, struct svalue *base_sp, int args, struct svalue *val, struct svalue *ind, char *desc, ...) ATTRIBUTE((noreturn,format (printf, 6, 7))); void bad_arg_error( char *func, struct svalue *base_sp, int args, int which_arg, char *expected_type, struct svalue *got, char *desc, ...) ATTRIBUTE((noreturn,format (printf, 7, 8)));
d0ed261999-03-20Fredrik Hübinette (Hubbe) void math_error( char *func, struct svalue *base_sp, int args,
c023d51999-03-23Fredrik Hübinette (Hubbe)  struct svalue *number,
b9f8361999-03-23Fredrik Hübinette (Hubbe)  char *desc, ...) ATTRIBUTE((noreturn,format (printf, 5, 6)));
d0ed261999-03-20Fredrik Hübinette (Hubbe) void resource_error( char *func, struct svalue *base_sp, int args, char *resource_type, long howmuch, char *desc, ...) ATTRIBUTE((noreturn,format (printf, 6, 7)));
424d9c1999-05-02Fredrik Hübinette (Hubbe) void permission_error( char *func, struct svalue *base_sp, int args, char *permission_type, char *desc, ...) ATTRIBUTE((noreturn, format(printf, 5, 6)));
81299f1999-03-19Fredrik Hübinette (Hubbe) void init_error(void); void cleanup_error(void);
e9f9141996-09-29Fredrik Hübinette (Hubbe) /* Prototypes end here */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5a7ab61998-01-31Fredrik Hübinette (Hubbe) #define fatal \ fprintf(stderr,"Fatal error at %s:%d\n",__FILE__,__LINE__),debug_fatal
54db6c1999-03-27Henrik Grubbström (Grubba) /* Some useful error macros. */ #define SIMPLE_BAD_ARG_ERROR(FUNC, ARG, EXPECT) \
a2ad152000-02-16Fredrik Hübinette (Hubbe)  bad_arg_error(FUNC, Pike_sp-args, args, ARG, EXPECT, Pike_sp+ARG-1-args,\
81299f1999-03-19Fredrik Hübinette (Hubbe)  "Bad argument %d to %s(). Expected %s\n", \ ARG, FUNC, EXPECT)
54db6c1999-03-27Henrik Grubbström (Grubba) #define SIMPLE_TOO_FEW_ARGS_ERROR(FUNC, ARG) \
a2ad152000-02-16Fredrik Hübinette (Hubbe)  bad_arg_error(FUNC, Pike_sp-args, args, ARG, "void", 0,\
81299f1999-03-19Fredrik Hübinette (Hubbe)  "Too few arguments to %s().\n",FUNC)
54db6c1999-03-27Henrik Grubbström (Grubba) #define SIMPLE_OUT_OF_MEMORY_ERROR(FUNC, AMOUNT) \
a2ad152000-02-16Fredrik Hübinette (Hubbe)  resource_error(FUNC, Pike_sp-args, args, "memory", AMOUNT, "Out of memory.\n")
5267b71995-08-09Fredrik Hübinette (Hubbe) 
54db6c1999-03-27Henrik Grubbström (Grubba) #define SIMPLE_DIVISION_BY_ZERO_ERROR(FUNC) \
a2ad152000-02-16Fredrik Hübinette (Hubbe)  math_error(FUNC, Pike_sp-args, args, 0, "Division by zero.\n")
5267b71995-08-09Fredrik Hübinette (Hubbe) 
54db6c1999-03-27Henrik Grubbström (Grubba) #endif
a4ec321999-04-09Fredrik Hübinette (Hubbe) 
0236db2000-12-04Fredrik Hübinette (Hubbe) /* forward compatibility */ #define Pike_error error
a4ec321999-04-09Fredrik Hübinette (Hubbe) #ifndef PIKE_DEBUG #define check_recovery_context() ((void)0) #endif