e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
b3d3742002-11-23Martin Stjernholm || $Id: error.c,v 1.93 2002/11/23 14:41:56 mast Exp $
e576bb2002-10-11Martin Nilsson */
aedfb12002-10-09Martin Nilsson 
be9ba12000-07-06Fredrik Hübinette (Hubbe) #define NO_PIKE_SHORTHAND
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
aad99b2001-03-28Fredrik Hübinette (Hubbe) #include "svalue.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "interpret.h" #include "stralloc.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "builtin_functions.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "array.h" #include "object.h"
ef7c761998-03-24Fredrik Hübinette (Hubbe) #include "main.h" #include "builtin_functions.h"
c08c8b1998-04-05Fredrik Hübinette (Hubbe) #include "backend.h"
4406cf1998-04-13Henrik Grubbström (Grubba) #include "operators.h"
81299f1999-03-19Fredrik Hübinette (Hubbe) #include "module_support.h"
db40ab1999-04-15Fredrik Hübinette (Hubbe) #include "threads.h"
20513c2000-04-12Fredrik Hübinette (Hubbe) #include "gc.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b3d3742002-11-23Martin Stjernholm RCSID("$Id: error.c,v 1.93 2002/11/23 14:41:56 mast Exp $");
24ddc71998-03-28Henrik Grubbström (Grubba) 
e9f9141996-09-29Fredrik Hübinette (Hubbe) #undef ATTRIBUTE #define ATTRIBUTE(X)
c299402001-11-10Martin Stjernholm PMOD_EXPORT const char msg_fatal_error[] = "%s:%d: Fatal error:\n"; #ifdef PIKE_DEBUG PMOD_EXPORT const char msg_unsetjmp_nosync_1[] = "UNSETJMP out of sync! (last SETJMP at %s)!\n"; PMOD_EXPORT const char msg_unsetjmp_nosync_2[] = "UNSETJMP out of sync! (Pike_interpreter.recoveries = 0)\n"; PMOD_EXPORT const char msg_last_setjmp[] = "LAST SETJMP: %s\n"; PMOD_EXPORT const char msg_unset_onerr_nosync_1[] = "UNSET_ONERROR out of sync (%p != %p).\n" "Last SET_ONERROR is from %s\n"; PMOD_EXPORT const char msg_unset_onerr_nosync_2[] = "UNSET_ONERROR out of sync. No Pike_interpreter.recoveries left.\n"; PMOD_EXPORT const char msg_assert_onerr[] = "%s ASSERT_ONERROR(%p) failed\n"; #endif PMOD_EXPORT const char msg_bad_arg[] = "Bad argument %d to %s(). Expected %s\n"; PMOD_EXPORT const char msg_too_few_args[] = "Too few arguments to %s().\n"; PMOD_EXPORT const char msg_out_of_mem[] = "Out of memory.\n"; PMOD_EXPORT const char msg_div_by_zero[] = "Division by zero.\n";
15e5e92000-08-15Henrik Grubbström (Grubba) /*
7c0df72001-02-06Henrik Grubbström (Grubba)  * Attempt to inhibit throwing of errors if possible. * Used by exit_on_error() to avoid infinite sprintf() loops. */ int Pike_inhibit_errors = 0; /*
15e5e92000-08-15Henrik Grubbström (Grubba)  * Recoveries handling. */ JMP_BUF *recoveries=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
c857761999-03-16Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void check_recovery_context(void)
c857761999-03-16Fredrik Hübinette (Hubbe) { char foo;
fc26f62000-07-06Fredrik Hübinette (Hubbe) #define TESTILITEST ((((char *)Pike_interpreter.recoveries)-((char *)&foo))*STACK_DIRECTION)
15e5e92000-08-15Henrik Grubbström (Grubba)  if(Pike_interpreter.recoveries && TESTILITEST > 0) {
e0755c2000-08-15Henrik Grubbström (Grubba)  fprintf(stderr, "Recoveries is out biking (Pike_interpreter.recoveries=%p, Pike_sp=%p, %ld)!\n", Pike_interpreter.recoveries, &foo, DO_NOT_WARN((long)TESTILITEST));
36fd7c2001-11-08Fredrik Hübinette (Hubbe)  fprintf(stderr, "Last recovery was added at %s\n", Pike_interpreter.recoveries->file);
5aad932002-08-15Marcus Comstedt  Pike_fatal("Recoveries is out biking (Pike_interpreter.recoveries=%p, Pike_sp=%p, %ld)!\n",
e0755c2000-08-15Henrik Grubbström (Grubba)  Pike_interpreter.recoveries, &foo, DO_NOT_WARN((long)TESTILITEST));
15e5e92000-08-15Henrik Grubbström (Grubba)  }
c857761999-03-16Fredrik Hübinette (Hubbe)  /* Add more stuff here when required */ }
5c6d382002-09-21Martin Stjernholm #endif
20f7a02000-03-20Fredrik Hübinette (Hubbe) 
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void pike_gdb_breakpoint(void)
20f7a02000-03-20Fredrik Hübinette (Hubbe) { }
c857761999-03-16Fredrik Hübinette (Hubbe) 
b3d3742002-11-23Martin Stjernholm PMOD_EXPORT JMP_BUF *init_recovery(JMP_BUF *r, size_t stack_pop_levels DEBUG_LINE_ARGS)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
c857761999-03-16Fredrik Hübinette (Hubbe)  check_recovery_context();
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
36fd7c2001-11-08Fredrik Hübinette (Hubbe)  r->file=location; OED_FPRINTF((stderr, "init_recovery(%p) %s\n", r, location));
5196c51998-07-16Fredrik Hübinette (Hubbe) #endif
fc26f62000-07-06Fredrik Hübinette (Hubbe)  r->frame_pointer=Pike_fp;
b3d3742002-11-23Martin Stjernholm  r->stack_pointer=Pike_sp - stack_pop_levels - Pike_interpreter.evaluator_stack;
fc26f62000-07-06Fredrik Hübinette (Hubbe)  r->mark_sp=Pike_mark_sp - Pike_interpreter.mark_stack; r->previous=Pike_interpreter.recoveries;
07513e1996-10-04Fredrik Hübinette (Hubbe)  r->onerror=0;
61e9a01998-01-25Fredrik Hübinette (Hubbe)  r->severity=THROW_ERROR;
fc26f62000-07-06Fredrik Hübinette (Hubbe)  Pike_interpreter.recoveries=r;
c857761999-03-16Fredrik Hübinette (Hubbe)  check_recovery_context();
e9f9141996-09-29Fredrik Hübinette (Hubbe)  return r;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
c4c6db2000-08-21Henrik Grubbström (Grubba) PMOD_EXPORT DECLSPEC(noreturn) void pike_throw(void) ATTRIBUTE((noreturn))
5267b71995-08-09Fredrik Hübinette (Hubbe) {
fc26f62000-07-06Fredrik Hübinette (Hubbe)  while(Pike_interpreter.recoveries && throw_severity > Pike_interpreter.recoveries->severity)
61e9a01998-01-25Fredrik Hübinette (Hubbe)  {
fc26f62000-07-06Fredrik Hübinette (Hubbe)  while(Pike_interpreter.recoveries->onerror)
61e9a01998-01-25Fredrik Hübinette (Hubbe)  {
fc26f62000-07-06Fredrik Hübinette (Hubbe)  (*Pike_interpreter.recoveries->onerror->func)(Pike_interpreter.recoveries->onerror->arg); Pike_interpreter.recoveries->onerror=Pike_interpreter.recoveries->onerror->previous;
61e9a01998-01-25Fredrik Hübinette (Hubbe)  }
fc26f62000-07-06Fredrik Hübinette (Hubbe)  Pike_interpreter.recoveries=Pike_interpreter.recoveries->previous;
61e9a01998-01-25Fredrik Hübinette (Hubbe)  }
fc26f62000-07-06Fredrik Hübinette (Hubbe)  if(!Pike_interpreter.recoveries)
5aad932002-08-15Marcus Comstedt  Pike_fatal("No error recovery context.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
fc26f62000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp - Pike_interpreter.evaluator_stack < Pike_interpreter.recoveries->stack_pointer)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Stack error in error.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
fc26f62000-07-06Fredrik Hübinette (Hubbe)  while(Pike_fp != Pike_interpreter.recoveries->frame_pointer)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
fc26f62000-07-06Fredrik Hübinette (Hubbe)  if(!Pike_fp)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Popped out of stack frames.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
424d9c1999-05-02Fredrik Hübinette (Hubbe)  POP_PIKE_FRAME();
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
fc26f62000-07-06Fredrik Hübinette (Hubbe)  pop_n_elems(Pike_sp - Pike_interpreter.evaluator_stack - Pike_interpreter.recoveries->stack_pointer); Pike_mark_sp = Pike_interpreter.mark_stack + Pike_interpreter.recoveries->mark_sp;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
fc26f62000-07-06Fredrik Hübinette (Hubbe)  while(Pike_interpreter.recoveries->onerror)
cb22561995-10-11Fredrik Hübinette (Hubbe)  {
fc26f62000-07-06Fredrik Hübinette (Hubbe)  (*Pike_interpreter.recoveries->onerror->func)(Pike_interpreter.recoveries->onerror->arg); Pike_interpreter.recoveries->onerror=Pike_interpreter.recoveries->onerror->previous;
cb22561995-10-11Fredrik Hübinette (Hubbe)  }
36fd7c2001-11-08Fredrik Hübinette (Hubbe) #if defined(DEBUG_MALLOC) && defined(PIKE_DEBUG) /* This will tell us where the value was caught (I hope) */ if(throw_value.type <= MAX_REF_TYPE) { debug_malloc_update_location(throw_value.u.refs, Pike_interpreter.recoveries->file); debug_malloc_touch(throw_value.u.refs); } #endif
fc26f62000-07-06Fredrik Hübinette (Hubbe)  longjmp(Pike_interpreter.recoveries->recovery,1);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
66a1572001-01-12Martin Stjernholm PMOD_EXPORT void push_error(const char *description)
f52cf61998-04-10Henrik Grubbström (Grubba) { push_text(description); f_backtrace(0); f_aggregate(2); }
2fbeae2001-07-01Martin Stjernholm PMOD_EXPORT struct svalue throw_value = { PIKE_T_INT, 0, #ifdef HAVE_UNION_INIT {0}, /* Only to avoid warnings. */ #endif };
61e9a01998-01-25Fredrik Hübinette (Hubbe) int throw_severity;
4406cf1998-04-13Henrik Grubbström (Grubba) static const char *in_error;
db40ab1999-04-15Fredrik Hübinette (Hubbe) 
fcec352000-12-04Martin Stjernholm PMOD_EXPORT DECLSPEC(noreturn) void low_error(const char *buf) ATTRIBUTE((noreturn))
db40ab1999-04-15Fredrik Hübinette (Hubbe) { push_error(buf); free_svalue(& throw_value);
fc26f62000-07-06Fredrik Hübinette (Hubbe)  throw_value = *--Pike_sp;
cfa2e51999-12-07Henrik Grubbström (Grubba)  throw_severity = THROW_ERROR;
db40ab1999-04-15Fredrik Hübinette (Hubbe)  in_error=0; pike_throw(); /* Hope someone is catching, or we will be out of balls. */ }
f52cf61998-04-10Henrik Grubbström (Grubba) /* FIXME: NOTE: This function uses a static buffer. * Check sizes of arguments passed! */
c4c6db2000-08-21Henrik Grubbström (Grubba) void DECLSPEC(noreturn) va_error(const char *fmt, va_list args) ATTRIBUTE((noreturn))
5267b71995-08-09Fredrik Hübinette (Hubbe) {
52cf141998-05-15Henrik Grubbström (Grubba)  char buf[4096];
db40ab1999-04-15Fredrik Hübinette (Hubbe)  SWAP_IN_THREAD_IF_REQUIRED();
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(in_error) {
4406cf1998-04-13Henrik Grubbström (Grubba)  const char *tmp=in_error;
5267b71995-08-09Fredrik Hübinette (Hubbe)  in_error=0;
5aad932002-08-15Marcus Comstedt  Pike_fatal("Recursive error() calls, original error: %s",tmp);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
5fe7a71995-11-06Fredrik Hübinette (Hubbe)  in_error=buf;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
52cf141998-05-15Henrik Grubbström (Grubba) #ifdef HAVE_VSNPRINTF
f00ecc1998-05-16Fredrik Hübinette (Hubbe)  vsnprintf(buf, 4090, fmt, args);
52cf141998-05-15Henrik Grubbström (Grubba) #else /* !HAVE_VSNPRINTF */
5267b71995-08-09Fredrik Hübinette (Hubbe)  VSPRINTF(buf, fmt, args);
52cf141998-05-15Henrik Grubbström (Grubba) #endif /* HAVE_VSNPRINTF */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
fc26f62000-07-06Fredrik Hübinette (Hubbe)  if(!Pike_interpreter.recoveries)
06983f1996-09-22Fredrik Hübinette (Hubbe)  {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
c4670c2002-09-24Martin Stjernholm  if (d_flag) { fprintf(stderr,"No error recovery context!\n%s",buf); dump_backlog(); }
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
a4a1722000-12-05Per Hedbor  fprintf(stderr,"No error recovery context!\n%s",buf);
06983f1996-09-22Fredrik Hübinette (Hubbe)  exit(99); }
e0755c2000-08-15Henrik Grubbström (Grubba)  if((size_t)strlen(buf) >= (size_t)sizeof(buf))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Buffer overflow in error()\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
db40ab1999-04-15Fredrik Hübinette (Hubbe)  low_error(buf);
f52cf61998-04-10Henrik Grubbström (Grubba) }
c4c6db2000-08-21Henrik Grubbström (Grubba) PMOD_EXPORT DECLSPEC(noreturn) void new_error(const char *name, const char *text, struct svalue *oldsp,
4406cf1998-04-13Henrik Grubbström (Grubba)  INT32 args, const char *file, int line) ATTRIBUTE((noreturn))
f52cf61998-04-10Henrik Grubbström (Grubba) { int i;
db40ab1999-04-15Fredrik Hübinette (Hubbe)  ASSERT_THREAD_SWAPPED_IN();
f52cf61998-04-10Henrik Grubbström (Grubba)  if(in_error) {
4406cf1998-04-13Henrik Grubbström (Grubba)  const char *tmp=in_error;
f52cf61998-04-10Henrik Grubbström (Grubba)  in_error=0;
5aad932002-08-15Marcus Comstedt  Pike_fatal("Recursive error() calls, original error: %s",tmp);
f52cf61998-04-10Henrik Grubbström (Grubba)  } in_error=text;
fc26f62000-07-06Fredrik Hübinette (Hubbe)  if(!Pike_interpreter.recoveries)
f52cf61998-04-10Henrik Grubbström (Grubba)  {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
c4670c2002-09-24Martin Stjernholm  if (d_flag) { fprintf(stderr,"No error recovery context!\n%s():%s",name,text); dump_backlog(); }
f52cf61998-04-10Henrik Grubbström (Grubba) #endif
a4a1722000-12-05Per Hedbor  fprintf(stderr,"No error recovery context!\n%s():%s",name,text);
68581a2000-01-29Fredrik Hübinette (Hubbe)  if(file) fprintf(stderr,"at %s:%d\n",file,line);
f52cf61998-04-10Henrik Grubbström (Grubba)  exit(99); } push_text(text);
5267b71995-08-09Fredrik Hübinette (Hubbe)  f_backtrace(0);
f52cf61998-04-10Henrik Grubbström (Grubba)  if (file) { push_text(file); push_int(line); } else { push_int(0); push_int(0); } push_text(name); for (i=-args; i; i++) { push_svalue(oldsp + i); } f_aggregate(args + 3); f_aggregate(1); f_add(2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  f_aggregate(2);
f52cf61998-04-10Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_svalue(& throw_value);
fc26f62000-07-06Fredrik Hübinette (Hubbe)  throw_value = *--Pike_sp;
61e9a01998-01-25Fredrik Hübinette (Hubbe)  throw_severity=THROW_ERROR;
5267b71995-08-09Fredrik Hübinette (Hubbe)  in_error=0;
dc7cc91998-01-14Fredrik Hübinette (Hubbe)  pike_throw(); /* Hope someone is catching, or we will be out of balls. */
5267b71995-08-09Fredrik Hübinette (Hubbe) }
c299402001-11-10Martin Stjernholm PMOD_EXPORT void exit_on_error(const void *msg)
dceabb1996-10-09Fredrik Hübinette (Hubbe) {
56275c2000-04-16Fredrik Hübinette (Hubbe)  ONERROR tmp; SET_ONERROR(tmp,fatal_on_error,"Fatal in exit_on_error!");
111fdd2000-04-17Fredrik Hübinette (Hubbe)  d_flag=0;
56275c2000-04-16Fredrik Hübinette (Hubbe) 
7c0df72001-02-06Henrik Grubbström (Grubba)  /* Tell sprintf(), describe_svalue() et al not to throw errors * if possible. */ Pike_inhibit_errors = 1;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
c4670c2002-09-24Martin Stjernholm  if (d_flag) { fprintf(stderr,"%s\n",(char *)msg); dump_backlog(); }
dceabb1996-10-09Fredrik Hübinette (Hubbe) #endif fprintf(stderr,"%s\n",(char *)msg);
05756c1999-08-24Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG { char *s;
a4a1722000-12-05Per Hedbor  fprintf(stderr,"Attempting to dump raw error: (may fail)\n");
05756c1999-08-24Fredrik Hübinette (Hubbe)  init_buf(); describe_svalue(&throw_value,0,0); s=simple_free_buf(); fprintf(stderr,"%s\n",s); free(s); } #endif
dceabb1996-10-09Fredrik Hübinette (Hubbe)  exit(1); }
47ebd32000-09-01Henrik Grubbström (Grubba) #ifdef __NT__ /* Wrapper around abort() to avoid interactive requesters on NT. */
8919b22001-09-27Fredrik Hübinette (Hubbe) int fnordel=0;
47ebd32000-09-01Henrik Grubbström (Grubba) static void do_abort() { if (!d_flag && !getenv("PIKE_DEBUG")) { exit(-6); /* -SIGIOT */ }
8919b22001-09-27Fredrik Hübinette (Hubbe)  fnordel=999/fnordel;
47ebd32000-09-01Henrik Grubbström (Grubba) } #else /* !__NT__ */ #define do_abort() abort() #endif /* __NT__ */
c299402001-11-10Martin Stjernholm PMOD_EXPORT void fatal_on_error(const void *msg)
dceabb1996-10-09Fredrik Hübinette (Hubbe) {
64bf102002-03-26Martin Stjernholm  /* It's ok if we're exiting. */ if (throw_severity == THROW_EXIT) return;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
c4670c2002-09-24Martin Stjernholm  if (d_flag) { fprintf(stderr,"%s\n",(char *)msg); dump_backlog(); }
dceabb1996-10-09Fredrik Hübinette (Hubbe) #endif fprintf(stderr,"%s\n",(char *)msg);
47ebd32000-09-01Henrik Grubbström (Grubba)  do_abort();
dceabb1996-10-09Fredrik Hübinette (Hubbe) }
b2d3e42000-12-01Fredrik Hübinette (Hubbe) PMOD_EXPORT DECLSPEC(noreturn) void Pike_error(const char *fmt,...) ATTRIBUTE((noreturn,format (printf, 1, 2)))
5267b71995-08-09Fredrik Hübinette (Hubbe) { va_list args; va_start(args,fmt); va_error(fmt,args); va_end(args); }
c4c6db2000-08-21Henrik Grubbström (Grubba) PMOD_EXPORT DECLSPEC(noreturn) void debug_fatal(const char *fmt, ...) ATTRIBUTE((noreturn,format (printf, 1, 2)))
5267b71995-08-09Fredrik Hübinette (Hubbe) { va_list args; static int in_fatal = 0;
a5cd6a2001-09-24Henrik Grubbström (Grubba)  /* fprintf(stderr, "Raw error: %s\n", fmt); */
5267b71995-08-09Fredrik Hübinette (Hubbe)  va_start(args,fmt); /* Prevent double fatal. */ if (in_fatal) { (void)VFPRINTF(stderr, fmt, args);
47ebd32000-09-01Henrik Grubbström (Grubba)  do_abort();
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
a3bcd72000-04-16Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  in_fatal = 1;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
c4670c2002-09-24Martin Stjernholm  if (d_flag) { (void)VFPRINTF(stderr, fmt, args); dump_backlog(); }
5c6d382002-09-21Martin Stjernholm #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
1216c42001-12-09Martin Stjernholm  if(Pike_in_gc) fprintf(stderr,"Pike was in GC stage %d when this fatal occured:\n",Pike_in_gc); Pike_in_gc = GC_PASS_DISABLED;
a3bcd72000-04-16Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  (void)VFPRINTF(stderr, fmt, args);
ef7c761998-03-24Fredrik Hübinette (Hubbe)  d_flag=t_flag=0;
f75ff92002-03-10Martin Stjernholm  if(Pike_sp && Pike_interpreter.evaluator_stack && master_object && master_object->prog)
111fdd2000-04-17Fredrik Hübinette (Hubbe)  { fprintf(stderr,"Attempting to dump backlog (may fail)...\n"); push_error("Backtrace at time of fatal:\n"); APPLY_MASTER("describe_backtrace",1);
cd86322000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp[-1].type==PIKE_T_STRING)
fc26f62000-07-06Fredrik Hübinette (Hubbe)  write_to_stderr(Pike_sp[-1].u.string->str, Pike_sp[-1].u.string->len);
111fdd2000-04-17Fredrik Hübinette (Hubbe)  }else{ fprintf(stderr,"No stack - no backtrace.\n"); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  fflush(stderr);
47ebd32000-09-01Henrik Grubbström (Grubba)  do_abort();
5267b71995-08-09Fredrik Hübinette (Hubbe) }
c857761999-03-16Fredrik Hübinette (Hubbe) 
81299f1999-03-19Fredrik Hübinette (Hubbe) #if 1
c857761999-03-16Fredrik Hübinette (Hubbe) 
7c0df72001-02-06Henrik Grubbström (Grubba) /*! @class Error */
81299f1999-03-19Fredrik Hübinette (Hubbe) #define ERR_DECLARE #include "errors.h"
7c0df72001-02-06Henrik Grubbström (Grubba) /*! @decl array cast(string type) *! *! Cast operator. *! *! @note *! The only supported type to cast to is @tt{"array"@}, which *! generates and old-style error. */
cec4222001-08-16Martin Stjernholm static void f_error_cast(INT32 args)
81299f1999-03-19Fredrik Hübinette (Hubbe) { char *s;
a4a1722000-12-05Per Hedbor  get_all_args("error->cast",args,"%s",&s);
81299f1999-03-19Fredrik Hübinette (Hubbe)  if(!strncmp(s,"array",5)) { pop_n_elems(args);
4eb01f2002-08-15Marcus Comstedt  if(GENERIC_ERROR_THIS->desc) ref_push_string(GENERIC_ERROR_THIS->desc); else push_int(0); if(GENERIC_ERROR_THIS->backtrace) ref_push_array(GENERIC_ERROR_THIS->backtrace); else push_int(0);
81299f1999-03-19Fredrik Hübinette (Hubbe)  f_aggregate(2); }else{
a4a1722000-12-05Per Hedbor  SIMPLE_BAD_ARG_ERROR("error->cast", 1, "the value \"array\"");
81299f1999-03-19Fredrik Hübinette (Hubbe)  } }
7c0df72001-02-06Henrik Grubbström (Grubba) /*! @decl array|string `[](int(0..1) index) *! *! Index operator. *! *! Simulates an array *! @array *! @elem string msg *! Error message. *! @elem array backtrace *! Backtrace as returned by @[backtrace()] from where *! the error occurred. *! @endarray *! *! @note *! The error message is always terminated with a newline. *! *! @seealso *! @[backtrace()] */
cec4222001-08-16Martin Stjernholm static void f_error_index(INT32 args)
81299f1999-03-19Fredrik Hübinette (Hubbe) {
65a5492000-08-10Per Hedbor  INT_TYPE ind;
a4a1722000-12-05Per Hedbor  get_all_args("error->`[]",args,"%i",&ind);
81299f1999-03-19Fredrik Hübinette (Hubbe)  switch(ind) {
53a2051999-10-06Henrik Grubbström (Grubba)  case 0: pop_n_elems(args);
4eb01f2002-08-15Marcus Comstedt  if(GENERIC_ERROR_THIS->desc) ref_push_string(GENERIC_ERROR_THIS->desc); else push_int(0);
53a2051999-10-06Henrik Grubbström (Grubba)  break; case 1: pop_n_elems(args);
4eb01f2002-08-15Marcus Comstedt  if(GENERIC_ERROR_THIS->backtrace) ref_push_array(GENERIC_ERROR_THIS->backtrace); else push_int(0);
53a2051999-10-06Henrik Grubbström (Grubba)  break;
81299f1999-03-19Fredrik Hübinette (Hubbe)  default:
a4a1722000-12-05Per Hedbor  index_error("error->`[]", Pike_sp-args, args, NULL, Pike_sp-args,
18099a2001-03-04Mirar (Pontus Hagland)  "Index %"PRINTPIKEINT"d is out of range 0 - 1.\n", ind);
53a2051999-10-06Henrik Grubbström (Grubba)  break;
81299f1999-03-19Fredrik Hübinette (Hubbe)  } }
7c0df72001-02-06Henrik Grubbström (Grubba) /*! @decl string describe() *! *! Make a readable error-message. *! *! @note *! Uses @[describe_backtrace()] to generate the message. */
cec4222001-08-16Martin Stjernholm static void f_error_describe(INT32 args)
81299f1999-03-19Fredrik Hübinette (Hubbe) { pop_n_elems(args);
fc26f62000-07-06Fredrik Hübinette (Hubbe)  ref_push_object(Pike_fp->current_object);
81299f1999-03-19Fredrik Hübinette (Hubbe)  APPLY_MASTER("describe_backtrace",1); }
7c0df72001-02-06Henrik Grubbström (Grubba) /*! @decl array backtrace() *! *! Get the backtrace from where the error occurred. *! *! @seealso *! @[predef::backtrace()] */
cec4222001-08-16Martin Stjernholm static void f_error_backtrace(INT32 args)
81299f1999-03-19Fredrik Hübinette (Hubbe) { pop_n_elems(args);
4eb01f2002-08-15Marcus Comstedt  if(GENERIC_ERROR_THIS->backtrace) ref_push_array(GENERIC_ERROR_THIS->backtrace); else push_int(0);
81299f1999-03-19Fredrik Hübinette (Hubbe) }
cec4222001-08-16Martin Stjernholm /*! @decl string _sprintf() */ static void f_error__sprintf(INT32 args) { struct program *p = Pike_fp->current_object->prog; int i = find_identifier("error_type", p); struct identifier *id = ID_FROM_INT(p, i); pop_n_elems(args); push_svalue(&PROG_FROM_INT(p, i)->constants[id->func.offset].sval); push_constant_text("(%O)");
4eb01f2002-08-15Marcus Comstedt  if(GENERIC_ERROR_THIS->desc) ref_push_string(GENERIC_ERROR_THIS->desc); else push_int(0);
cec4222001-08-16Martin Stjernholm  f_sprintf(2); f_add(2); }
4eb01f2002-08-15Marcus Comstedt /*! @decl void create(string message) */ static void f_error_create(INT32 args) { struct pike_string *msg; get_all_args("create", args, "%W", &msg); do_free_string(GENERIC_ERROR_THIS->desc); copy_shared_string(GENERIC_ERROR_THIS->desc, msg); f_backtrace(0); push_int (0); push_int (Pike_sp[-2].u.array->size-2); o_range (); assign_to_short_svalue ((union anything *)&GENERIC_ERROR_THIS->backtrace, PIKE_T_ARRAY, Pike_sp-1); pop_n_elems(args+1); }
7c0df72001-02-06Henrik Grubbström (Grubba) /*! @endclass */
cfa2e51999-12-07Henrik Grubbström (Grubba) #ifdef ERROR_DEBUG #define DWERROR(X) fprintf X #else /* !ERROR_DEBUG */ #define DWERROR(X) #endif /* ERROR_DEBUG */
81299f1999-03-19Fredrik Hübinette (Hubbe) #define INIT_ERROR(FEL)\ va_list foo; \
db40ab1999-04-15Fredrik Hübinette (Hubbe)  struct object *o; \ va_start(foo,desc); \ ASSERT_THREAD_SWAPPED_IN(); \
cfa2e51999-12-07Henrik Grubbström (Grubba)  o=low_clone(PIKE_CONCAT(FEL,_error_program)); \
a4a1722000-12-05Per Hedbor  DWERROR((stderr, "%s(): Throwing a " #FEL " error\n", func))
81299f1999-03-19Fredrik Hübinette (Hubbe)  #define ERROR_DONE(FOO) \ PIKE_CONCAT(FOO,_error_va(o,func, \ base_sp, args, \ desc,foo)); \ va_end(foo) #define ERROR_STRUCT(STRUCT,O) \ ((struct PIKE_CONCAT(STRUCT,_error_struct) *)((O)->storage + PIKE_CONCAT(STRUCT,_error_offset))) #define ERROR_COPY(STRUCT,X) \ ERROR_STRUCT(STRUCT,o)->X=X
b4185e2000-04-04Henrik Grubbström (Grubba) #define ERROR_COPY_SVALUE(STRUCT,X) do { \ if (X) { \ assign_svalue_no_free( & ERROR_STRUCT(STRUCT,o)->X, X); \ } else { \
cd86322000-07-06Fredrik Hübinette (Hubbe)  ERROR_STRUCT(STRUCT, o)->X.type = PIKE_T_INT; \
b4185e2000-04-04Henrik Grubbström (Grubba)  ERROR_STRUCT(STRUCT, o)->X.subtype = 0; \ ERROR_STRUCT(STRUCT, o)->X.u.integer = 0; \ } \ } while (0)
81299f1999-03-19Fredrik Hübinette (Hubbe)  #define ERROR_COPY_REF(STRUCT,X) \ add_ref( ERROR_STRUCT(STRUCT,o)->X=X )
c4c6db2000-08-21Henrik Grubbström (Grubba) DECLSPEC(noreturn) void generic_error_va(struct object *o,
c299402001-11-10Martin Stjernholm  const char *func,
c4c6db2000-08-21Henrik Grubbström (Grubba)  struct svalue *base_sp, int args,
c299402001-11-10Martin Stjernholm  const char *fmt,
c4c6db2000-08-21Henrik Grubbström (Grubba)  va_list foo) ATTRIBUTE((noreturn))
c857761999-03-16Fredrik Hübinette (Hubbe) { char buf[8192];
81299f1999-03-19Fredrik Hübinette (Hubbe)  int i;
c857761999-03-16Fredrik Hübinette (Hubbe)  #ifdef HAVE_VSNPRINTF
81299f1999-03-19Fredrik Hübinette (Hubbe)  vsnprintf(buf, sizeof(buf)-1, fmt, foo);
c857761999-03-16Fredrik Hübinette (Hubbe) #else /* !HAVE_VSNPRINTF */
53a2051999-10-06Henrik Grubbström (Grubba)  /* Sentinel that will be overwritten on buffer overflow. */ buf[sizeof(buf)-1] = '\0';
81299f1999-03-19Fredrik Hübinette (Hubbe)  VSPRINTF(buf, fmt, foo);
c857761999-03-16Fredrik Hübinette (Hubbe) 
53a2051999-10-06Henrik Grubbström (Grubba)  if(buf[sizeof(buf)-1])
5aad932002-08-15Marcus Comstedt  Pike_fatal("Buffer overflow in error()\n");
c857761999-03-16Fredrik Hübinette (Hubbe) #endif /* HAVE_VSNPRINTF */
81299f1999-03-19Fredrik Hübinette (Hubbe)  in_error=buf;
c857761999-03-16Fredrik Hübinette (Hubbe) 
17fd852000-08-15Henrik Grubbström (Grubba)  if (!master_program) {
15e5e92000-08-15Henrik Grubbström (Grubba)  fprintf(stderr, "ERROR: %s\n", buf); }
81299f1999-03-19Fredrik Hübinette (Hubbe)  ERROR_STRUCT(generic,o)->desc=make_shared_string(buf); f_backtrace(0); if(func) { push_int(0); push_int(0); push_text(func);
e88b9e1999-04-02Fredrik Hübinette (Hubbe)  for (i=0;i<args;i++)
81299f1999-03-19Fredrik Hübinette (Hubbe)  push_svalue(base_sp + i); f_aggregate(args + 3); f_aggregate(1); f_add(2); }
c857761999-03-16Fredrik Hübinette (Hubbe) 
cd86322000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp[-1].type!=PIKE_T_ARRAY)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Error failed to generate a backtrace!\n");
81299f1999-03-19Fredrik Hübinette (Hubbe) 
fc26f62000-07-06Fredrik Hübinette (Hubbe)  ERROR_STRUCT(generic,o)->backtrace=Pike_sp[-1].u.array; Pike_sp--; dmalloc_touch_svalue(Pike_sp);
81299f1999-03-19Fredrik Hübinette (Hubbe)  free_svalue(& throw_value);
cd86322000-07-06Fredrik Hübinette (Hubbe)  throw_value.type=PIKE_T_OBJECT;
81299f1999-03-19Fredrik Hübinette (Hubbe)  throw_value.u.object=o;
a373381999-07-27Henrik Grubbström (Grubba)  throw_severity = THROW_ERROR;
c857761999-03-16Fredrik Hübinette (Hubbe)  in_error=0;
36fd7c2001-11-08Fredrik Hübinette (Hubbe)  dmalloc_touch_svalue(& throw_value);
c857761999-03-16Fredrik Hübinette (Hubbe)  pike_throw(); /* Hope someone is catching, or we will be out of balls. */ }
78283b2001-08-16Martin Stjernholm  PMOD_EXPORT DECLSPEC(noreturn) void throw_error_object( struct object *o,
c299402001-11-10Martin Stjernholm  const char *func,
78283b2001-08-16Martin Stjernholm  struct svalue *base_sp, int args,
c299402001-11-10Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn,format (printf, 5, 6)))
78283b2001-08-16Martin Stjernholm { va_list foo; va_start(foo,desc); ASSERT_THREAD_SWAPPED_IN(); DWERROR((stderr, "%s(): Throwing an error object\n", func)); ERROR_DONE(generic); }
c4c6db2000-08-21Henrik Grubbström (Grubba) PMOD_EXPORT DECLSPEC(noreturn) void generic_error(
c299402001-11-10Martin Stjernholm  const char *func,
81299f1999-03-19Fredrik Hübinette (Hubbe)  struct svalue *base_sp, int args,
c299402001-11-10Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn,format (printf, 4, 5)))
c857761999-03-16Fredrik Hübinette (Hubbe) {
81299f1999-03-19Fredrik Hübinette (Hubbe)  INIT_ERROR(generic); ERROR_DONE(generic);
c857761999-03-16Fredrik Hübinette (Hubbe) }
c4c6db2000-08-21Henrik Grubbström (Grubba) PMOD_EXPORT DECLSPEC(noreturn) void index_error(
c299402001-11-10Martin Stjernholm  const char *func,
81299f1999-03-19Fredrik Hübinette (Hubbe)  struct svalue *base_sp, int args, struct svalue *val, struct svalue *ind,
c299402001-11-10Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn,format (printf, 6, 7)))
81299f1999-03-19Fredrik Hübinette (Hubbe) { INIT_ERROR(index); ERROR_COPY_SVALUE(index, val); ERROR_COPY_SVALUE(index, ind); ERROR_DONE(generic); }
c857761999-03-16Fredrik Hübinette (Hubbe) 
c4c6db2000-08-21Henrik Grubbström (Grubba) PMOD_EXPORT DECLSPEC(noreturn) void bad_arg_error(
c299402001-11-10Martin Stjernholm  const char *func,
81299f1999-03-19Fredrik Hübinette (Hubbe)  struct svalue *base_sp, int args, int which_arg,
c299402001-11-10Martin Stjernholm  const char *expected_type,
81299f1999-03-19Fredrik Hübinette (Hubbe)  struct svalue *got,
c299402001-11-10Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn,format (printf, 7, 8)))
c857761999-03-16Fredrik Hübinette (Hubbe) {
81299f1999-03-19Fredrik Hübinette (Hubbe)  INIT_ERROR(bad_arg); ERROR_COPY(bad_arg, which_arg); ERROR_STRUCT(bad_arg,o)->expected_type=make_shared_string(expected_type); if(got) { ERROR_COPY_SVALUE(bad_arg, got); }else{
cd86322000-07-06Fredrik Hübinette (Hubbe)  ERROR_STRUCT(bad_arg,o)->got.type=PIKE_T_INT;
81299f1999-03-19Fredrik Hübinette (Hubbe)  ERROR_STRUCT(bad_arg,o)->got.subtype=NUMBER_UNDEFINED; ERROR_STRUCT(bad_arg,o)->got.u.integer=0; }
cfa2e51999-12-07Henrik Grubbström (Grubba)  DWERROR((stderr, "%s():Bad arg %d (expected %s)\n", func, which_arg, expected_type));
81299f1999-03-19Fredrik Hübinette (Hubbe)  ERROR_DONE(generic); }
c857761999-03-16Fredrik Hübinette (Hubbe) 
c4c6db2000-08-21Henrik Grubbström (Grubba) PMOD_EXPORT DECLSPEC(noreturn) void math_error(
c299402001-11-10Martin Stjernholm  const char *func,
d0ed261999-03-20Fredrik Hübinette (Hubbe)  struct svalue *base_sp, int args,
28af0c1999-03-23Fredrik Hübinette (Hubbe)  struct svalue *number,
c299402001-11-10Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn,format (printf, 5, 6)))
d0ed261999-03-20Fredrik Hübinette (Hubbe) { INIT_ERROR(math);
28af0c1999-03-23Fredrik Hübinette (Hubbe)  if(number) {
c023d51999-03-23Fredrik Hübinette (Hubbe)  ERROR_COPY_SVALUE(math, number);
28af0c1999-03-23Fredrik Hübinette (Hubbe)  }else{
cd86322000-07-06Fredrik Hübinette (Hubbe)  ERROR_STRUCT(math,o)->number.type=PIKE_T_INT;
c023d51999-03-23Fredrik Hübinette (Hubbe)  ERROR_STRUCT(math,o)->number.subtype=NUMBER_UNDEFINED; ERROR_STRUCT(math,o)->number.u.integer=0;
28af0c1999-03-23Fredrik Hübinette (Hubbe)  }
d0ed261999-03-20Fredrik Hübinette (Hubbe)  ERROR_DONE(generic); }
c4c6db2000-08-21Henrik Grubbström (Grubba) PMOD_EXPORT DECLSPEC(noreturn) void resource_error(
c299402001-11-10Martin Stjernholm  const char *func,
d0ed261999-03-20Fredrik Hübinette (Hubbe)  struct svalue *base_sp, int args,
c299402001-11-10Martin Stjernholm  const char *resource_type,
4f62cb2000-08-15Henrik Grubbström (Grubba)  size_t howmuch_,
c299402001-11-10Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn,format (printf, 6, 7)))
d0ed261999-03-20Fredrik Hübinette (Hubbe) {
4f62cb2000-08-15Henrik Grubbström (Grubba)  INT_TYPE howmuch = DO_NOT_WARN((INT_TYPE)howmuch_);
d0ed261999-03-20Fredrik Hübinette (Hubbe)  INIT_ERROR(resource);
4f62cb2000-08-15Henrik Grubbström (Grubba)  ERROR_COPY(resource, howmuch);
d0ed261999-03-20Fredrik Hübinette (Hubbe)  ERROR_STRUCT(resource,o)->resource_type=make_shared_string(resource_type); ERROR_DONE(generic); }
c857761999-03-16Fredrik Hübinette (Hubbe) 
c4c6db2000-08-21Henrik Grubbström (Grubba) PMOD_EXPORT DECLSPEC(noreturn) void permission_error(
c299402001-11-10Martin Stjernholm  const char *func,
64dc4c1999-04-17Henrik Grubbström (Grubba)  struct svalue *base_sp, int args,
c299402001-11-10Martin Stjernholm  const char *permission_type, const char *desc, ...) ATTRIBUTE((noreturn, format(printf, 5, 6)))
64dc4c1999-04-17Henrik Grubbström (Grubba) { INIT_ERROR(permission); ERROR_STRUCT(permission,o)->permission_type= make_shared_string(permission_type); ERROR_DONE(generic); }
c299402001-11-10Martin Stjernholm PMOD_EXPORT void wrong_number_of_args_error(const char *name, int args, int expected)
3a5b1d2000-05-24Fredrik Hübinette (Hubbe) { char *msg; if(expected>args) { msg="Too few arguments"; }else{ msg="Too many arguments"; }
fc26f62000-07-06Fredrik Hübinette (Hubbe)  new_error(name, msg, Pike_sp-args, args, 0,0);
3a5b1d2000-05-24Fredrik Hübinette (Hubbe) }
20513c2000-04-12Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG static void gc_check_throw_value(struct callback *foo, void *bar, void *gazonk) { debug_gc_xmark_svalues(&throw_value,1," in the throw value"); } #endif
81299f1999-03-19Fredrik Hübinette (Hubbe) void init_error(void) { #define ERR_SETUP #include "errors.h"
20513c2000-04-12Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG dmalloc_accept_leak(add_gc_callback(gc_check_throw_value,0,0)); #endif
81299f1999-03-19Fredrik Hübinette (Hubbe) }
c857761999-03-16Fredrik Hübinette (Hubbe) 
81299f1999-03-19Fredrik Hübinette (Hubbe) void cleanup_error(void) { #define ERR_CLEANUP #include "errors.h"
c857761999-03-16Fredrik Hübinette (Hubbe) } #endif