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. */
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"
9ba1e52008-05-27Henrik Grubbström (Grubba) #include "mapping.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #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) 
8a28fd2004-05-19Martin Nilsson /* __attribute__ only applies to function declarations, not definitions, so we disable them here. */
e9f9141996-09-29Fredrik Hübinette (Hubbe) #undef ATTRIBUTE #define ATTRIBUTE(X)
9ba1e52008-05-27Henrik Grubbström (Grubba) /* #define ERROR_DEBUG */
c299402001-11-10Martin Stjernholm PMOD_EXPORT const char msg_fatal_error[] =
ef24a82012-01-12Henrik Grubbström (Grubba)  "%s:%ld: Fatal error:\n";
c299402001-11-10Martin Stjernholm #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[] =
91fd1d2003-01-04Martin Nilsson  "Bad argument %d to %s(). Expected %s.\n";
4e30de2003-03-28Martin Stjernholm PMOD_EXPORT const char msg_bad_arg_2[] = "Bad argument %d to %s(). %s\n";
c299402001-11-10Martin Stjernholm PMOD_EXPORT const char msg_out_of_mem[] = "Out of memory.\n";
40d6ed2006-05-10Martin Stjernholm PMOD_EXPORT const char msg_out_of_mem_2[] = "Out of memory - failed to allocate %"PRINTSIZET"d bytes.\n";
c299402001-11-10Martin Stjernholm PMOD_EXPORT const char msg_div_by_zero[] = "Division by zero.\n";
15e5e92000-08-15Henrik Grubbström (Grubba) /* * Recoveries handling. */
c857761999-03-16Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
9ba1e52008-05-27Henrik Grubbström (Grubba) /* struct mapping *recovery_lookup = NULL; */
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)
ca176b2006-02-27Martin Stjernholm  if(Pike_interpreter.recoveries && Pike_interpreter.recoveries->on_stack && 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));
5cd8d92008-05-27Henrik Grubbström (Grubba)  fprintf(stderr, "Last recovery was added at %s:%d\n",
9ba1e52008-05-27Henrik Grubbström (Grubba)  Pike_interpreter.recoveries->file, Pike_interpreter.recoveries->line); push_int((ptrdiff_t)Pike_interpreter.recoveries); /* if ((s = low_mapping_lookup(recovery_lookup, Pike_sp-1))) { */ /* fprintf(stderr, "Try also looking at %s.\n", (char*)s->u.integer); */ /* } */ pop_stack();
b7d8212006-03-25Henrik Grubbström (Grubba)  Pike_fatal("Recoveries is out biking (Pike_interpreter.recoveries=%p, C 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) 
071adc2002-11-25Martin Stjernholm PMOD_EXPORT void pike_gdb_breakpoint(INT32 args)
20f7a02000-03-20Fredrik Hübinette (Hubbe) {
3194842002-11-28Martin Stjernholm  pop_n_elems(args);
20f7a02000-03-20Fredrik Hübinette (Hubbe) }
c857761999-03-16Fredrik Hübinette (Hubbe) 
ca176b2006-02-27Martin Stjernholm PMOD_EXPORT JMP_BUF *init_recovery(JMP_BUF *r, size_t stack_pop_levels DEBUG_INIT_REC_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));
ca176b2006-02-27Martin Stjernholm  r->on_stack = on_stack;
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();
9ba1e52008-05-27Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG /* if (recovery_lookup && Pike_sp) { */ /* push_int((ptrdiff_t)r); */ /* push_int((ptrdiff_t)location); */ /* mapping_insert(recovery_lookup, Pike_sp-2, Pike_sp-1); */ /* pop_n_elems(2); */ /* } */ #endif
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) {
5035482019-10-19Henrik Grubbström (Grubba)  struct svalue save_throw_value; /* Save the value to be thrown in case error handlers etc below * call eg safe_apply() et al, or cause a thread switch to * code that does. */ move_svalue(&save_throw_value, &throw_value); mark_free_svalue(&throw_value);
01c63f2003-04-28Martin Stjernholm #ifdef TRACE_UNFINISHED_TYPE_FIELDS accept_unfinished_type_fields++; #endif
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)  {
a3b1dc2010-09-27Henrik Grubbström (Grubba)  ONERROR *err = Pike_interpreter.recoveries->onerror; while(Pike_fp != err->frame_pointer)
62384e2008-04-12Henrik Grubbström (Grubba)  { #ifdef PIKE_DEBUG if(!Pike_fp) Pike_fatal("Popped out of stack frames.\n"); #endif POP_PIKE_FRAME(); }
a3b1dc2010-09-27Henrik Grubbström (Grubba)  Pike_interpreter.recoveries->onerror = err->previous; (*err->func)(err->arg);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  }
ca176b2006-02-27Martin Stjernholm 
ce42902008-05-24Martin Stjernholm  { JMP_BUF *prev_rec = Pike_interpreter.recoveries->previous; if (Pike_interpreter.catch_ctx && (&Pike_interpreter.catch_ctx->recovery == Pike_interpreter.recoveries)) { struct catch_context *cc = Pike_interpreter.catch_ctx; Pike_interpreter.catch_ctx = cc->prev; really_free_catch_context (cc); } Pike_interpreter.recoveries = prev_rec;
ca176b2006-02-27Martin Stjernholm  }
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) 
fe79cd2007-07-04Henrik Grubbström (Grubba)  /* Don't pop the stack before the onerrors have run; they might need * items from the stack. */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
fc26f62000-07-06Fredrik Hübinette (Hubbe)  while(Pike_interpreter.recoveries->onerror)
cb22561995-10-11Fredrik Hübinette (Hubbe)  {
a3b1dc2010-09-27Henrik Grubbström (Grubba)  ONERROR *err = Pike_interpreter.recoveries->onerror; while(Pike_fp != err->frame_pointer)
62384e2008-04-12Henrik Grubbström (Grubba)  { #ifdef PIKE_DEBUG if(!Pike_fp) Pike_fatal("Popped out of stack frames.\n"); #endif POP_PIKE_FRAME(); }
a3b1dc2010-09-27Henrik Grubbström (Grubba)  Pike_interpreter.recoveries->onerror = err->previous; (*err->func)(err->arg);
cb22561995-10-11Fredrik Hübinette (Hubbe)  }
62384e2008-04-12Henrik Grubbström (Grubba)  while(Pike_fp != Pike_interpreter.recoveries->frame_pointer) { #ifdef PIKE_DEBUG if(!Pike_fp) Pike_fatal("Popped out of stack frames.\n"); #endif POP_PIKE_FRAME(); }
fe79cd2007-07-04Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if(Pike_sp - Pike_interpreter.evaluator_stack < Pike_interpreter.recoveries->stack_pointer) Pike_fatal("Stack error in error.\n"); #endif
5035482019-10-19Henrik Grubbström (Grubba)  /* Note: The pop_n_elems below may trigger destruct callbacks being called * for objects having PROGRAM_DESTRUCT_IMMEDIATE. These may * in turn throw (caught) errors and zap throw_value. */
fe79cd2007-07-04Henrik Grubbström (Grubba)  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;
5035482019-10-19Henrik Grubbström (Grubba)  /* Move the value to be thrown back so that it can be caught. */ free_svalue(&throw_value); move_svalue(&throw_value, &save_throw_value);
36fd7c2001-11-08Fredrik Hübinette (Hubbe) #if defined(DEBUG_MALLOC) && defined(PIKE_DEBUG) /* This will tell us where the value was caught (I hope) */
4a93e82013-06-11Henrik Grubbström (Grubba)  if(REFCOUNTED_TYPE(TYPEOF(throw_value)))
36fd7c2001-11-08Fredrik Hübinette (Hubbe)  { debug_malloc_update_location(throw_value.u.refs, Pike_interpreter.recoveries->file); debug_malloc_touch(throw_value.u.refs); } #endif
01c63f2003-04-28Martin Stjernholm #ifdef TRACE_UNFINISHED_TYPE_FIELDS accept_unfinished_type_fields--; #endif
ca176b2006-02-27Martin Stjernholm  if (Pike_interpreter.catch_ctx && &Pike_interpreter.catch_ctx->recovery == Pike_interpreter.recoveries) { /* This is a phony recovery made in F_CATCH that hasn't been passed * to LOW_SETJMP. The real jmpbuf is in catching_eval_instruction. */ #ifdef PIKE_DEBUG if (!Pike_interpreter.catching_eval_jmpbuf) Pike_fatal ("Got phony F_CATCH recovery but no catching_eval_jmpbuf.\n"); #endif LOW_LONGJMP (*Pike_interpreter.catching_eval_jmpbuf, 1); } else LOW_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); }
8133372008-05-30Martin Stjernholm PMOD_EXPORT struct svalue throw_value = SVALUE_INIT_FREE;
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);
c621452003-11-14Martin Stjernholm  move_svalue (&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. */ }
d5ff1b2008-10-04Martin Stjernholm PMOD_EXPORT void va_make_error (const char *fmt, va_list args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
d0f82b2004-11-11Henrik Grubbström (Grubba)  struct string_builder s;
d5ff1b2008-10-04Martin Stjernholm  init_string_builder(&s, 0); string_builder_vsprintf(&s, fmt, args); push_string(finish_string_builder(&s)); f_backtrace(0); f_aggregate(2); }
d0f82b2004-11-11Henrik Grubbström (Grubba) 
d5ff1b2008-10-04Martin Stjernholm PMOD_EXPORT void DECLSPEC(noreturn) va_error(const char *fmt, va_list args) ATTRIBUTE((noreturn)) {
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;
d0f82b2004-11-11Henrik Grubbström (Grubba)  in_error = NULL;
d5ff1b2008-10-04Martin Stjernholm  Pike_fatal("Recursive Pike_error() calls, " "original error: %s, new error: %s", tmp, fmt);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
d0f82b2004-11-11Henrik Grubbström (Grubba)  in_error=fmt;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
fc26f62000-07-06Fredrik Hübinette (Hubbe)  if(!Pike_interpreter.recoveries)
06983f1996-09-22Fredrik Hübinette (Hubbe)  {
d0f82b2004-11-11Henrik Grubbström (Grubba)  /* FIXME: Why not use Pike_fatal() here? */
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
c4670c2002-09-24Martin Stjernholm  if (d_flag) {
f3cf182008-10-04Martin Stjernholm  fprintf(stderr,"No error recovery context!\n%s", fmt);
c4670c2002-09-24Martin Stjernholm  dump_backlog(); }
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
f3cf182008-10-04Martin Stjernholm  fprintf(stderr,"No error recovery context!\n%s", fmt);
06983f1996-09-22Fredrik Hübinette (Hubbe)  exit(99); }
d5ff1b2008-10-04Martin Stjernholm  va_make_error (fmt, args);
d0f82b2004-11-11Henrik Grubbström (Grubba)  free_svalue(&throw_value); move_svalue(&throw_value, --Pike_sp); throw_severity = THROW_ERROR; in_error = NULL; pike_throw(); /* Hope someone is catching, or we will be out of balls. */
f52cf61998-04-10Henrik Grubbström (Grubba) }
d5ff1b2008-10-04Martin Stjernholm PMOD_EXPORT void make_error (const char *fmt, ...) /* Creates a general error container like Pike_error but doesn't throw * it, instead it is left on the stack. */ { va_list args; va_start (args,fmt); va_make_error (fmt,args); va_end (args); }
46781c2012-12-02Peter Bortas /* coverity[+kill] */
d5ff1b2008-10-04Martin Stjernholm PMOD_EXPORT DECLSPEC(noreturn) void Pike_error(const char *fmt,...) ATTRIBUTE((noreturn)) { va_list args; va_start(args,fmt); va_error(fmt,args); va_end(args); }
d0f82b2004-11-11Henrik Grubbström (Grubba) PMOD_EXPORT DECLSPEC(noreturn) void new_error(const char *name, const char *text, struct svalue *oldsp, 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) {
2624d22003-07-30Martin Stjernholm  fprintf(stderr,"No error recovery context!\n%s():%s", name ? name : "<unknown>", text);
c4670c2002-09-24Martin Stjernholm  dump_backlog(); }
f52cf61998-04-10Henrik Grubbström (Grubba) #endif
2624d22003-07-30Martin Stjernholm  fprintf(stderr,"No error recovery context!\n%s():%s", name ? name : "<unknown>", 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); }
83bc4f2003-07-30Martin Stjernholm  if (name) push_text(name); else push_int(0);
f52cf61998-04-10Henrik Grubbström (Grubba)  for (i=-args; i; i++) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(oldsp[i]) <= PIKE_T_FLOAT) {
cbc0622003-09-19Henrik Grubbström (Grubba)  push_svalue(oldsp + i); } else { char buffer[50]; sprintf(buffer, "<Svalue:0x%04x:0x%04x:%p>",
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(oldsp[i]), SUBTYPEOF(oldsp[i]), oldsp[i].u.ptr);
cbc0622003-09-19Henrik Grubbström (Grubba)  push_text(buffer); }
f52cf61998-04-10Henrik Grubbström (Grubba)  } 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) 
d0f82b2004-11-11Henrik Grubbström (Grubba)  free_svalue(&throw_value);
c621452003-11-14Martin Stjernholm  move_svalue (&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) }
30def62004-06-01Martin Stjernholm static int inhibit_errors = 0;
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;
30def62004-06-01Martin Stjernholm  Pike_interpreter.trace_level = 0;
56275c2000-04-16Fredrik Hübinette (Hubbe) 
30def62004-06-01Martin Stjernholm  if (inhibit_errors) fprintf (stderr, "Got recursive error in exit_on_error: %s\n", (char *) msg);
7c0df72001-02-06Henrik Grubbström (Grubba) 
30def62004-06-01Martin Stjernholm  else {
9fa0ee2003-11-09Martin Stjernholm  dynamic_buffer save_buf;
05756c1999-08-24Fredrik Hübinette (Hubbe)  char *s;
c8cdaf2003-07-16Martin Stjernholm  struct svalue thrown;
30def62004-06-01Martin Stjernholm  inhibit_errors = 1; #ifdef PIKE_DEBUG if (d_flag) { fprintf(stderr,"%s\n",(char *)msg); dump_backlog(); } #endif fprintf(stderr,"%s\n",(char *)msg); /* We've reserved LOW_SVALUE_STACK_MARGIN and LOW_C_STACK_MARGIN * for this. */ Pike_interpreter.svalue_stack_margin = 0; Pike_interpreter.c_stack_margin = 0;
a4a1722000-12-05Per Hedbor  fprintf(stderr,"Attempting to dump raw error: (may fail)\n");
9fa0ee2003-11-09Martin Stjernholm  init_buf(&save_buf);
c8cdaf2003-07-16Martin Stjernholm  move_svalue (&thrown, &throw_value);
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&throw_value);
c8cdaf2003-07-16Martin Stjernholm  describe_svalue(&thrown,0,0); free_svalue (&thrown);
9fa0ee2003-11-09Martin Stjernholm  s=simple_free_buf(&save_buf);
05756c1999-08-24Fredrik Hübinette (Hubbe)  fprintf(stderr,"%s\n",s); free(s); }
30def62004-06-01Martin Stjernholm 
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")) {
7d24f72004-06-29Henrik Grubbström (Grubba)  exit(-6); /* -SIGIOT */
47ebd32000-09-01Henrik Grubbström (Grubba)  }
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) }
987ef42007-06-17Martin Stjernholm PMOD_EXPORT DECLSPEC(noreturn) void debug_va_fatal(const char *fmt, va_list args) ATTRIBUTE((noreturn))
5267b71995-08-09Fredrik Hübinette (Hubbe) { static int in_fatal = 0;
a5cd6a2001-09-24Henrik Grubbström (Grubba)  /* fprintf(stderr, "Raw error: %s\n", fmt); */
5267b71995-08-09Fredrik Hübinette (Hubbe)  /* Prevent double fatal. */ if (in_fatal) {
f6249c2008-03-29Martin Stjernholm  if (fmt) (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) {
f6249c2008-03-29Martin Stjernholm #ifdef HAVE_VA_COPY
6361e12008-03-29Martin Stjernholm  if (fmt) { va_list a;
f6249c2008-03-29Martin Stjernholm  va_copy (a, args);
6361e12008-03-29Martin Stjernholm  (void)VFPRINTF(stderr, fmt, a); va_end (a); }
f6249c2008-03-29Martin Stjernholm #endif
c4670c2002-09-24Martin Stjernholm  dump_backlog(); }
5c6d382002-09-21Martin Stjernholm #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
987ef42007-06-17Martin Stjernholm  if (fmt) (void)VFPRINTF(stderr, fmt, args);
1216c42001-12-09Martin Stjernholm  if(Pike_in_gc)
3a5f8e2010-02-21Stephen R. van den Berg  fprintf(stderr,"Pike was in GC stage %d when this fatal occurred.\n",Pike_in_gc);
1216c42001-12-09Martin Stjernholm  Pike_in_gc = GC_PASS_DISABLED;
a3bcd72000-04-16Fredrik Hübinette (Hubbe) 
97ebb32003-01-09Henrik Grubbström (Grubba)  d_flag=Pike_interpreter.trace_level=0;
8d01422004-09-18Henrik Grubbström (Grubba) 
f75ff92002-03-10Martin Stjernholm  if(Pike_sp && Pike_interpreter.evaluator_stack && master_object && master_object->prog)
111fdd2000-04-17Fredrik Hübinette (Hubbe)  {
01b2442004-02-09Martin Stjernholm  JMP_BUF jmp; struct callback_list saved_eval_cbs = evaluator_callbacks;
7279d92009-03-13Martin Stjernholm  /* Simulate threads_disabled to avoid thread switches or any other * evaluator stuff while we let the master describe the backtrace * below. Doing it the naughty way without going through * init_threads_disable etc to avoid hanging on runaway locks. */ threads_disabled++;
01b2442004-02-09Martin Stjernholm  MEMSET (&evaluator_callbacks, 0, sizeof (evaluator_callbacks)); if (SETJMP (jmp)) fprintf(stderr,"Got exception when trying to describe backtrace.\n"); else { jmp.severity = THROW_EXIT; /* Don't want normal exit code to run here. */ push_error("Backtrace at time of fatal:\n"); APPLY_MASTER("describe_backtrace",1);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) == PIKE_T_STRING)
01b2442004-02-09Martin Stjernholm  write_to_stderr(Pike_sp[-1].u.string->str, Pike_sp[-1].u.string->len); } UNSETJMP (jmp);
7279d92009-03-13Martin Stjernholm  threads_disabled--;
01b2442004-02-09Martin Stjernholm  evaluator_callbacks = saved_eval_cbs;
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) 
46781c2012-12-02Peter Bortas /* coverity[+kill] */
987ef42007-06-17Martin Stjernholm PMOD_EXPORT DECLSPEC(noreturn) void debug_fatal(const char *fmt, ...) ATTRIBUTE((noreturn)) { va_list args; va_start(args,fmt); debug_va_fatal (fmt, args); va_end (args); }
81299f1999-03-19Fredrik Hübinette (Hubbe) #if 1
c857761999-03-16Fredrik Hübinette (Hubbe) 
2e7de82002-12-07Henrik Grubbström (Grubba) /*! @class MasterObject */ /*! @decl string describe_backtrace(mixed exception) *! *! Called by various routines to format a readable *! description of an exception. *! *! @param exception
c59b922004-04-20Martin Nilsson  *! Something that was thrown. Usually an @[Error.Generic] object, or
2e7de82002-12-07Henrik Grubbström (Grubba)  *! an array with the following content: *! @array *! @elem string msg *! Error message. *! @elem array(backtrace_frame|array(mixed)) backtrace *! Backtrace to the point where the exception occurred. *! @endarray *! *! @returns *! Returns a string describing the exeception. *! *! @note *! Usually added by the initialization code the global name space *! with @[add_constant()]. *! *! @seealso *! @[predef::describe_backtrace()] */ /*! @endclass */
c59b922004-04-20Martin Nilsson /*! @module Error */ /*! @class Generic *! Class for exception objects for errors of unspecified type.
7c0df72001-02-06Henrik Grubbström (Grubba)  */
0269592006-09-20Martin Stjernholm /*! @decl string error_message *! *! The error message. It always ends with a newline (@expr{'\n'@}) *! character and it might be more than one line. *! *! Code that catches and rethrows errors may extend this with more *! error information. */ /*! @decl array(backtrace_frame|array(mixed)) error_backtrace *! *! The backtrace as returned by @[backtrace] where the error *! occurred. *! *! Code that catches and rethrows errors should ensure that this *! remains the same in the rethrown error. */
a18d9a2008-05-27Martin Stjernholm #define GENERIC_ERROR_THIS ((struct generic_error_struct *)CURRENT_STORAGE)
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
cbe8c92003-04-07Martin Nilsson  *! The only supported type to cast to is @expr{"array"@}, which
0269592006-09-20Martin Stjernholm  *! generates an old-style error @expr{({@[message](), *! @[backtrace]()})@}.
7c0df72001-02-06Henrik Grubbström (Grubba)  */
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);
0269592006-09-20Martin Stjernholm  apply_current (generic_err_message_fun, 0); apply_current (generic_err_backtrace_fun, 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
0269592006-09-20Martin Stjernholm  *! Error message as returned by @[message].
7c0df72001-02-06Henrik Grubbström (Grubba)  *! @elem array backtrace
0269592006-09-20Martin Stjernholm  *! Backtrace as returned by @[backtrace].
7c0df72001-02-06Henrik Grubbström (Grubba)  *! @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);
0269592006-09-20Martin Stjernholm  apply_current (generic_err_message_fun, 0);
53a2051999-10-06Henrik Grubbström (Grubba)  break; case 1: pop_n_elems(args);
0269592006-09-20Martin Stjernholm  apply_current (generic_err_backtrace_fun, 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,
b99d882003-05-15Martin Stjernholm  "Index %"PRINTPIKEINT"d is out of range 0..1.\n", ind);
53a2051999-10-06Henrik Grubbström (Grubba)  break;
81299f1999-03-19Fredrik Hübinette (Hubbe)  } }
87f2e92013-06-10Henrik Grubbström (Grubba) static void f_error__sizeof(INT32 args) { pop_n_elems(args); push_int(2); } static void f_error__indices(INT32 args) { pop_n_elems(args); push_int(0); push_int(1); f_aggregate(2); } static void f_error__values(INT32 args) { pop_n_elems(args); apply_current(generic_err_message_fun, 0); apply_current(generic_err_backtrace_fun, 0); f_aggregate(2); }
7c0df72001-02-06Henrik Grubbström (Grubba) /*! @decl string describe() *!
e86c8c2003-11-14Martin Stjernholm  *! Return a readable error report that includes the backtrace.
7c0df72001-02-06Henrik Grubbström (Grubba)  */
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); }
e86c8c2003-11-14Martin Stjernholm /*! @decl string message() *!
0269592006-09-20Martin Stjernholm  *! Return a readable message describing the error. Normally simply *! returns @[error_message]. *! *! If you override this function then you should ensure that *! @[error_message] is included in the returned message, since there *! might be code that catches your error objects, extends *! @[error_message] with more info, and rethrows the error.
e86c8c2003-11-14Martin Stjernholm  */ static void f_error_message(INT32 args) { pop_n_elems(args); if (GENERIC_ERROR_THIS->error_message) ref_push_string (GENERIC_ERROR_THIS->error_message); else push_int (0); }
7c0df72001-02-06Henrik Grubbström (Grubba) /*! @decl array backtrace() *!
0269592006-09-20Martin Stjernholm  *! Return the backtrace where the error occurred. Normally simply *! returns @[error_backtrace].
7c0df72001-02-06Henrik Grubbström (Grubba)  *! *! @seealso *! @[predef::backtrace()] */
cec4222001-08-16Martin Stjernholm static void f_error_backtrace(INT32 args)
81299f1999-03-19Fredrik Hübinette (Hubbe) { pop_n_elems(args);
e86c8c2003-11-14Martin Stjernholm  if(GENERIC_ERROR_THIS->error_backtrace) ref_push_array(GENERIC_ERROR_THIS->error_backtrace);
4eb01f2002-08-15Marcus Comstedt  else push_int(0);
81299f1999-03-19Fredrik Hübinette (Hubbe) }
cec4222001-08-16Martin Stjernholm /*! @decl string _sprintf() */ static void f_error__sprintf(INT32 args) {
e6dbc22002-11-29Marcus Comstedt  int mode = 0;
a18d9a2008-05-27Martin Stjernholm 
017b572011-10-28Henrik Grubbström (Grubba)  if(args>0 && TYPEOF(Pike_sp[-args]) == PIKE_T_INT)
e6dbc22002-11-29Marcus Comstedt  mode = Pike_sp[-args].u.integer;
cec4222001-08-16Martin Stjernholm  pop_n_elems(args);
a18d9a2008-05-27Martin Stjernholm 
e6dbc22002-11-29Marcus Comstedt  if(mode != 'O') { push_undefined(); return; }
a18d9a2008-05-27Martin Stjernholm  { struct program *p = Pike_fp->current_object->prog; int i; struct pike_string *error_name_str; /* error_name is the name the error program wants in printouts * like this. To still let inheriting programs fall back to * describe_program if they don't provide it, we make it private * in the base error classes and allow us to see private * identifiers here. */ MAKE_CONST_STRING (error_name_str, "error_name"); i = really_low_find_shared_string_identifier (error_name_str, p, SEE_PRIVATE); if (i != -1) push_svalue (&PROG_FROM_INT (p, i)->
89378b2010-11-23Henrik Grubbström (Grubba)  constants[ID_FROM_INT (p, i)->func.const_info.offset].sval);
a18d9a2008-05-27Martin Stjernholm  else { ref_push_program (p); SAFE_APPLY_MASTER ("describe_program", 1); } }
cec4222001-08-16Martin Stjernholm  push_constant_text("(%O)");
e86c8c2003-11-14Martin Stjernholm  if(GENERIC_ERROR_THIS->error_message) ref_push_string(GENERIC_ERROR_THIS->error_message);
4eb01f2002-08-15Marcus Comstedt  else push_int(0);
cec4222001-08-16Martin Stjernholm  f_sprintf(2);
a18d9a2008-05-27Martin Stjernholm  f_add(2);
cec4222001-08-16Martin Stjernholm }
7383542006-08-21Henrik Grubbström (Grubba) /*! @decl int(0..1) _is_type(string t) *!
0269592006-09-20Martin Stjernholm  *! Claims that the error object is an array, for compatibility with *! old style error handling code.
7383542006-08-21Henrik Grubbström (Grubba)  */ static void f_error__is_type(INT32 args) { struct pike_string *array_string; int ret; MAKE_CONST_STRING(array_string, "array"); if (args < 0) SIMPLE_TOO_FEW_ARGS_ERROR("_is_type", 1); if (args > 1) SIMPLE_WRONG_NUM_ARGS_ERROR("_is_type", 1);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-args]) != PIKE_T_STRING)
7383542006-08-21Henrik Grubbström (Grubba)  SIMPLE_ARG_TYPE_ERROR("_is_type", 1, "string"); ret = Pike_sp[-args].u.string == array_string; pop_n_elems(args); push_int(ret); }
0269592006-09-20Martin Stjernholm /*! @decl void create(string message, @ *! void|array(backtrace_frame|array(mixed)) backtrace)
4eb01f2002-08-15Marcus Comstedt  */ static void f_error_create(INT32 args) { struct pike_string *msg;
1dc55b2004-12-17Martin Stjernholm  struct array *bt = NULL; get_all_args("create", args, "%W.%A", &msg, &bt);
e86c8c2003-11-14Martin Stjernholm  do_free_string(GENERIC_ERROR_THIS->error_message); copy_shared_string(GENERIC_ERROR_THIS->error_message, msg);
1dc55b2004-12-17Martin Stjernholm  if (bt) { if (GENERIC_ERROR_THIS->error_backtrace) free_array (GENERIC_ERROR_THIS->error_backtrace); add_ref (GENERIC_ERROR_THIS->error_backtrace = bt); } else { f_backtrace(0); push_int (1); o_range2 (RANGE_LOW_OPEN|RANGE_HIGH_FROM_END); assign_to_short_svalue ((union anything *)&GENERIC_ERROR_THIS->error_backtrace, PIKE_T_ARRAY, Pike_sp-1); pop_stack(); } pop_n_elems(args);
4eb01f2002-08-15Marcus Comstedt }
7c0df72001-02-06Henrik Grubbström (Grubba) /*! @endclass */
c59b922004-04-20Martin Nilsson /*! @endmodule */
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(); \
11149d2009-07-17Henrik Grubbström (Grubba)  DWERROR((stderr, "%s(): Throwing a " #FEL " error\n", func)); \ o=fast_clone_object(PIKE_CONCAT(FEL,_error_program))
81299f1999-03-19Fredrik Hübinette (Hubbe)  #define ERROR_DONE(FOO) \ PIKE_CONCAT(FOO,_error_va(o,func, \
55af8e2008-05-27Henrik Grubbström (Grubba)  base_sp, args, \ desc, &foo)); \
81299f1999-03-19Fredrik Hübinette (Hubbe)  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 { \
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(ERROR_STRUCT(STRUCT, o)->X, PIKE_T_INT, NUMBER_UNDEFINED, \
8581e52011-11-05Martin Nilsson  integer, 0); \
b4185e2000-04-04Henrik Grubbström (Grubba)  } \ } while (0)
81299f1999-03-19Fredrik Hübinette (Hubbe)  #define ERROR_COPY_REF(STRUCT,X) \ add_ref( ERROR_STRUCT(STRUCT,o)->X=X )
30533b2008-05-27Martin Stjernholm /* This prepares the passed object o, which is assumed to inherit * generic_error_program, and throws it:
93be412008-05-27Martin Stjernholm  *
30533b2008-05-27Martin Stjernholm  * o A backtrace is assigned to error_backtrace.
93be412008-05-27Martin Stjernholm  *
30533b2008-05-27Martin Stjernholm  * o If func is specified, a frame is constructed for at the end of * backtrace using it as function name and base_sp[0..args-1] as * arguments.
93be412008-05-27Martin Stjernholm  *
30533b2008-05-27Martin Stjernholm  * o If fmt is specified, an error message is created from it and * fmt_args using string_builder_vsprintf. (fmt_args is passed as a * va_list pointer to be able to pass NULL if fmt is NULL.) */ PMOD_EXPORT DECLSPEC(noreturn) void generic_error_va( struct object *o, const char *func, const struct svalue *base_sp, int args,
55af8e2008-05-27Henrik Grubbström (Grubba)  const char *fmt, va_list *fmt_args)
c857761999-03-16Fredrik Hübinette (Hubbe) {
30533b2008-05-27Martin Stjernholm  struct generic_error_struct *err = (struct generic_error_struct *) get_storage (o, generic_error_program); #ifdef PIKE_DEBUG if (!err) Pike_fatal ("Got an object which doesn't inherit generic_error_program.\n"); #endif
c857761999-03-16Fredrik Hübinette (Hubbe) 
2dbc882002-12-16Martin Stjernholm  if(in_error) { const char *tmp=in_error; in_error=0;
55af8e2008-05-27Henrik Grubbström (Grubba)  Pike_fatal("Recursive error() calls, original error: %s", tmp);
2dbc882002-12-16Martin Stjernholm  }
30533b2008-05-27Martin Stjernholm  in_error = fmt ? fmt : "no error message";
564e332004-11-11Henrik Grubbström (Grubba) 
30533b2008-05-27Martin Stjernholm  if (fmt) { struct string_builder s; init_string_builder(&s, 0);
55af8e2008-05-27Henrik Grubbström (Grubba)  string_builder_vsprintf(&s, fmt, *fmt_args);
c857761999-03-16Fredrik Hübinette (Hubbe) 
4833172003-07-22Martin Stjernholm #if 0
30533b2008-05-27Martin Stjernholm  if (!master_program) { fprintf(stderr, "ERROR: %s\n", s.s->str); }
4833172003-07-22Martin Stjernholm #endif
15e5e92000-08-15Henrik Grubbström (Grubba) 
db14502008-05-27Henrik Grubbström (Grubba)  if (err->error_message) free_string(err->error_message);
30533b2008-05-27Martin Stjernholm  err->error_message = finish_string_builder(&s); }
81299f1999-03-19Fredrik Hübinette (Hubbe)  f_backtrace(0); if(func) {
30533b2008-05-27Martin Stjernholm  int i;
81299f1999-03-19Fredrik Hübinette (Hubbe)  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) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) != PIKE_T_ARRAY)
30533b2008-05-27Martin Stjernholm  Pike_fatal("f_backtrace failed to generate a backtrace!\n");
81299f1999-03-19Fredrik Hübinette (Hubbe) 
db14502008-05-27Henrik Grubbström (Grubba)  if (err->error_backtrace) free_array(err->error_backtrace);
30533b2008-05-27Martin Stjernholm  err->error_backtrace=Pike_sp[-1].u.array;
fc26f62000-07-06Fredrik Hübinette (Hubbe)  Pike_sp--; dmalloc_touch_svalue(Pike_sp);
81299f1999-03-19Fredrik Hübinette (Hubbe)  free_svalue(& throw_value);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(throw_value, PIKE_T_OBJECT, 0, 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 
db14502008-05-27Henrik Grubbström (Grubba) /* Throw a preallocated error object. * * NOTE: The object MUST NOT have been cloned by a plain low_clone()! * At least fast_clone_object() MUST have been used, or the object * data must have been properly initialized in some other way! */
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,
f38f282004-11-14Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn))
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,
f38f282004-11-14Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn))
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,
e86c8c2003-11-14Martin Stjernholm  struct svalue *value, struct svalue *index,
f38f282004-11-14Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn))
81299f1999-03-19Fredrik Hübinette (Hubbe) { INIT_ERROR(index);
e86c8c2003-11-14Martin Stjernholm  ERROR_COPY_SVALUE(index, value); ERROR_COPY_SVALUE(index, index);
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 bad_arg_error(
c299402001-11-10Martin Stjernholm  const char *func,
81299f1999-03-19Fredrik Hübinette (Hubbe)  struct svalue *base_sp, int args,
e86c8c2003-11-14Martin Stjernholm  int which_argument,
c299402001-11-10Martin Stjernholm  const char *expected_type,
e86c8c2003-11-14Martin Stjernholm  struct svalue *got_value,
f38f282004-11-14Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn))
c857761999-03-16Fredrik Hübinette (Hubbe) {
df019f2004-04-18Martin Stjernholm  INIT_ERROR(bad_argument); ERROR_COPY(bad_argument, which_argument);
81aa522003-04-01Martin Stjernholm  if (expected_type)
017b572011-10-28Henrik Grubbström (Grubba)  ERROR_STRUCT(bad_argument,o)->expected_type = make_shared_string(expected_type);
81aa522003-04-01Martin Stjernholm  else
df019f2004-04-18Martin Stjernholm  ERROR_STRUCT(bad_argument,o)->expected_type = NULL; ERROR_COPY_SVALUE(bad_argument, got_value);
cfa2e51999-12-07Henrik Grubbström (Grubba)  DWERROR((stderr, "%s():Bad arg %d (expected %s)\n",
9ba1e52008-05-27Henrik Grubbström (Grubba)  func, which_argument, 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,
f38f282004-11-14Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn))
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{
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(ERROR_STRUCT(math,o)->number, PIKE_T_INT, NUMBER_UNDEFINED, 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_,
f38f282004-11-14Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn))
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,
f38f282004-11-14Martin Stjernholm  const char *desc, ...) ATTRIBUTE((noreturn))
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) { if(expected>args) {
81aa522003-04-01Martin Stjernholm  bad_arg_error (name, Pike_sp-args, args, expected, NULL, NULL,
3372982004-10-22Henrik Grubbström (Grubba)  "Too few arguments to %s(). Expected at least %d (got %d).\n",
b9d3f32004-10-23Martin Nilsson  name, expected, args);
4e30de2003-03-28Martin Stjernholm  }else {
81aa522003-04-01Martin Stjernholm  bad_arg_error (name, Pike_sp-args, args, expected, NULL, NULL,
3372982004-10-22Henrik Grubbström (Grubba)  "Too many arguments to %s(). Expected at most %d (got %d).\n", name, expected, args);
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) {
e1a35e2003-09-08Martin Stjernholm  gc_mark_external_svalues(&throw_value,1," in the throw value");
20513c2000-04-12Fredrik Hübinette (Hubbe) } #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));
9ba1e52008-05-27Henrik Grubbström (Grubba)  /* recovery_lookup = allocate_mapping(100); */
20513c2000-04-12Fredrik Hübinette (Hubbe) #endif
81299f1999-03-19Fredrik Hübinette (Hubbe) }
c857761999-03-16Fredrik Hübinette (Hubbe) 
81299f1999-03-19Fredrik Hübinette (Hubbe) void cleanup_error(void) {
9ba1e52008-05-27Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG /* free_mapping(recovery_lookup); */ #endif
81299f1999-03-19Fredrik Hübinette (Hubbe) #define ERR_CLEANUP #include "errors.h"
c857761999-03-16Fredrik Hübinette (Hubbe) } #endif