Skip to content
Snippets Groups Projects
Select Git revision
  • fcec356756430b4a6c269411c05e84e80fc8f52f
  • master default protected
  • 9.0
  • 8.0
  • 7.8
  • 7.6
  • 7.4
  • 7.2
  • 7.0
  • 0.6
  • rosuav/latex-markdown-renderer
  • rxnpatch/rxnpatch
  • marcus/gobject-introspection
  • rxnpatch/8.0
  • rosuav/pre-listening-ports
  • nt-tools
  • rosuav/async-annotations
  • rosuav/pgsql-ssl
  • rxnpatch/rxnpatch-broken/2023-10-06T094250
  • grubba/fdlib
  • grubba/wip/sakura/8.0
  • v8.0.2000
  • v8.0.1998
  • v8.0.1996
  • v8.0.1994
  • v8.0.1992
  • v8.0.1990
  • v8.0.1988
  • v8.0.1986
  • rxnpatch/clusters/8.0/2025-04-29T124414
  • rxnpatch/2025-04-29T124414
  • v8.0.1984
  • v8.0.1982
  • v8.0.1980
  • v8.0.1978
  • v8.0.1976
  • v8.0.1974
  • v8.0.1972
  • v8.0.1970
  • v8.0.1968
  • v8.0.1966
41 results

error.c

Blame
  • error.c 18.30 KiB
    /*\
    ||| This file a part of Pike, and is copyright by Fredrik Hubinette
    ||| Pike is distributed as GPL (General Public License)
    ||| See the files COPYING and DISCLAIMER for more information.
    \*/
    /**/
    #define NO_PIKE_SHORTHAND
    #include "global.h"
    #include "pike_macros.h"
    #include "pike_error.h"
    #include "interpret.h"
    #include "stralloc.h"
    #include "builtin_functions.h"
    #include "array.h"
    #include "object.h"
    #include "main.h"
    #include "builtin_functions.h"
    #include "backend.h"
    #include "operators.h"
    #include "module_support.h"
    #include "threads.h"
    #include "gc.h"
    
    RCSID("$Id: error.c,v 1.66 2000/12/04 19:38:26 mast Exp $");
    
    #undef ATTRIBUTE
    #define ATTRIBUTE(X)
    
    /*
     * Backtrace handling.
     */
    
    struct pike_backtrace
    {
      struct pike_frame *trace;
      struct pike_frame *iterator;
      int iterator_index;
    };
    
    static struct program *frame_program = NULL;
    
    #define THIS_BT ((struct pike_backtrace *)Pike_fp->current_storage)
    
    static void init_backtrace(struct object *o)
    {
      MEMSET(THIS_BT, 0, sizeof(struct pike_backtrace));
    }
    
    static void exit_backtrace(struct object *o)
    {
      if (THIS_BT->trace) {
        free_pike_frame(THIS_BT->trace);
        THIS_BT->trace = NULL;
        THIS_BT->iterator = NULL;
      }
    }
    
    /* void create() */
    void f_bt_create(INT32 args)
    {
      if (THIS_BT->trace) {
        free_pike_frame(THIS_BT->trace);
      }
      add_ref(THIS_BT->trace = Pike_fp);
      THIS_BT->iterator = THIS_BT->trace;
      THIS_BT->iterator_index = 0;
      pop_n_elems(args);
      push_int(0);
    }
    
    /* int _sizeof() */
    static void f_bt__sizeof(INT32 args)
    {
      int size = 0;
      struct pike_frame *f = THIS_BT->iterator;
      size = THIS_BT->iterator_index;
      while (f) {
        size++;
        f = f->next;
      }
      pop_n_elems(args);
      push_int(size);
    }
    
    /* array(int) _indices() */
    static void f_bt__indices(INT32 args)
    {
      /* Not really optimal, but who performs indices() on a backtrace? */
      f_bt__sizeof(args);
      f_allocate(1);
      f_indices(1);
    }
    
    /* array _values() */
    static void f_bt__values(INT32 args)
    {
      struct pike_frame *f = THIS_BT->trace;
      struct array *a;
      int i;
      int sz;
      f_bt__sizeof(args);
      f_allocate(1);
      for (i=0, a=Pike_sp[-1].u.array, sz=a->size; (i < sz) && f; i++, f=f->next) {
        struct object *o = low_clone(frame_program);
        call_c_initializers(o);
        add_ref(*((struct pike_frame **)(o->storage)) = f);
        push_object(o);
        a->item[i] = Pike_sp[-1];
        Pike_sp--;
      }
    }
    
    /* object(frame) `[](int index) */
    static void f_bt__index(INT32 args)
    {
      INT_TYPE index;
      int i;
      struct pike_frame *f;
      struct object *o;
    
      get_all_args("backtrace->`[]", args, "%i", &index);
    
      if (index < 0) {
        /* Indexing from end not supported. */
        index_error("backtrace->`[]", Pike_sp-args, args, NULL, Pike_sp-args,
    		"Indexing with negative value (%d).\n", index);
      }
    
      if (index < THIS_BT->iterator_index) {
        THIS_BT->iterator = THIS_BT->trace;
        THIS_BT->iterator_index = 0;
      }
    
      f = THIS_BT->iterator;
      i = THIS_BT->iterator_index;
    
      while (f && (i < index)) {
        f = f->next;
        i++;
      }
      if (!f) {
        index_error("backtrace->`[]", Pike_sp-args, args, NULL, Pike_sp-args,
    		"Index out of range [0..%d].\n", i-1);
      }
      THIS_BT->iterator = f;
      THIS_BT->iterator_index = i;
      o = low_clone(frame_program);
      call_c_initializers(o);
      add_ref(*((struct pike_frame **)(o->storage)) = f);
      pop_n_elems(args);
      push_object(o);
    }
    
    /*
     * Frame handling.
     */
    
    #define THIS_PF		((struct pike_frame **)Pike_fp->current_storage)
    
    static void init_pike_frame(struct object *o)
    {
      THIS_PF[0] = NULL;
    }
    
    static void exit_pike_frame(struct object *o)
    {
      if (THIS_PF[0]) {
        free_pike_frame(THIS_PF[0]);
        THIS_PF[0] = NULL;
      }
    }
    
    /* mixed `[](int index) */
    static void f_pf__index(INT32 args)
    {
      INT_TYPE index;
      struct pike_frame *f;
    
      get_all_args("pike_frame->`[]", args, "%i", &index);
    
      f = THIS_PF[0];
    
      if (!f) {
        index_error("pike_frame->`[]", Pike_sp-args, args, NULL, Pike_sp-args,
    		"Indexing the empty array with %d.\n", index);
      }
      if (index < 0) {
        index_error("pike_frame->`[]", Pike_sp-args, args, NULL, Pike_sp-args,
    		"Indexing with negative index (%d)\n", index);
      }
      if (!(f->current_object && f->context.prog)) {
        index_error("pike_frame->`[]", Pike_sp-args, args, NULL, Pike_sp-args,
    		"Indexing the NULL value with %d.\n", index);
      }
      switch(index) {
      case 0:	/* Filename */
      case 1:	/* Linenumber */
        break;
      case 2:	/* Function */
        if (f->current_object->prog) {
          pop_n_elems(args);
          ref_push_object(f->current_object);
          Pike_sp[-1].subtype = f->fun;
          Pike_sp[-1].type = PIKE_T_FUNCTION;
        } else {
          pop_n_elems(args);
          push_int(0);
          Pike_sp[-1].subtype = NUMBER_DESTRUCTED;
        }
        return;
      default:	/* Arguments */
        break;
      }
    }
    
    /*
     * Recoveries handling.
     */
    
    JMP_BUF *recoveries=0;
    
    #ifdef PIKE_DEBUG
    PMOD_EXPORT void check_recovery_context(void)
    {
      char foo;
    #define TESTILITEST ((((char *)Pike_interpreter.recoveries)-((char *)&foo))*STACK_DIRECTION)
      if(Pike_interpreter.recoveries && TESTILITEST > 0) {
        fprintf(stderr, "Recoveries is out biking (Pike_interpreter.recoveries=%p, Pike_sp=%p, %ld)!\n",
    	    Pike_interpreter.recoveries, &foo,
    	    DO_NOT_WARN((long)TESTILITEST));
        fprintf(stderr, "Last recovery was added at %s:%d\n",
    	    Pike_interpreter.recoveries->file,
    	    Pike_interpreter.recoveries->line);
        fatal("Recoveries is out biking (Pike_interpreter.recoveries=%p, Pike_sp=%p, %ld)!\n",
    	  Pike_interpreter.recoveries, &foo,
    	  DO_NOT_WARN((long)TESTILITEST));
      }
    
      /* Add more stuff here when required */
    }
    
    PMOD_EXPORT void pike_gdb_breakpoint(void) 
    {
    }
    #endif
    
    PMOD_EXPORT JMP_BUF *init_recovery(JMP_BUF *r DEBUG_LINE_ARGS)
    {
      check_recovery_context();
    #ifdef PIKE_DEBUG
      r->line=line;
      r->file=file;
      OED_FPRINTF((stderr, "init_recovery(%p) %s:%d\n", r, file, line));
    #endif
      r->frame_pointer=Pike_fp;
      r->stack_pointer=Pike_sp-Pike_interpreter.evaluator_stack;
      r->mark_sp=Pike_mark_sp - Pike_interpreter.mark_stack;
      r->previous=Pike_interpreter.recoveries;
      r->onerror=0;
      r->severity=THROW_ERROR;
      Pike_interpreter.recoveries=r;
      check_recovery_context();
      return r;
    }
    
    PMOD_EXPORT DECLSPEC(noreturn) void pike_throw(void) ATTRIBUTE((noreturn))
    {
      while(Pike_interpreter.recoveries && throw_severity > Pike_interpreter.recoveries->severity)
      {
        while(Pike_interpreter.recoveries->onerror)
        {
          (*Pike_interpreter.recoveries->onerror->func)(Pike_interpreter.recoveries->onerror->arg);
          Pike_interpreter.recoveries->onerror=Pike_interpreter.recoveries->onerror->previous;
        }
        
        Pike_interpreter.recoveries=Pike_interpreter.recoveries->previous;
      }
    
      if(!Pike_interpreter.recoveries)
        fatal("No Pike_error recovery context.\n");
    
    #ifdef PIKE_DEBUG
      if(Pike_sp - Pike_interpreter.evaluator_stack < Pike_interpreter.recoveries->stack_pointer)
        fatal("Stack Pike_error in Pike_error.\n");
    #endif
    
      while(Pike_fp != Pike_interpreter.recoveries->frame_pointer)
      {
    #ifdef PIKE_DEBUG
        if(!Pike_fp)
          fatal("Popped out of stack frames.\n");
    #endif
        POP_PIKE_FRAME();
      }
    
      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;
    
      while(Pike_interpreter.recoveries->onerror)
      {
        (*Pike_interpreter.recoveries->onerror->func)(Pike_interpreter.recoveries->onerror->arg);
        Pike_interpreter.recoveries->onerror=Pike_interpreter.recoveries->onerror->previous;
      }
    
      longjmp(Pike_interpreter.recoveries->recovery,1);
    }
    
    PMOD_EXPORT void push_error(char *description)
    {
      push_text(description);
      f_backtrace(0);
      f_aggregate(2);
    }
    
    PMOD_EXPORT struct svalue throw_value = { PIKE_T_INT };
    int throw_severity;
    static const char *in_error;
    
    PMOD_EXPORT DECLSPEC(noreturn) void low_error(const char *buf) ATTRIBUTE((noreturn))
    {
      push_error(buf);
      free_svalue(& throw_value);
      throw_value = *--Pike_sp;
      throw_severity = THROW_ERROR;
      in_error=0;
      pike_throw();  /* Hope someone is catching, or we will be out of balls. */
    }
    
    /* FIXME: NOTE: This function uses a static buffer.
     * Check sizes of arguments passed!
     */
    void DECLSPEC(noreturn) va_error(const char *fmt, va_list args) ATTRIBUTE((noreturn))
    {
      char buf[4096];
      SWAP_IN_THREAD_IF_REQUIRED();
      if(in_error)
      {
        const char *tmp=in_error;
        in_error=0;
        fatal("Recursive Pike_error() calls, original Pike_error: %s",tmp);
      }
    
      in_error=buf;
    
    #ifdef HAVE_VSNPRINTF
      vsnprintf(buf, 4090, fmt, args);
    #else /* !HAVE_VSNPRINTF */
      VSPRINTF(buf, fmt, args);
    #endif /* HAVE_VSNPRINTF */
    
      if(!Pike_interpreter.recoveries)
      {
    #ifdef PIKE_DEBUG
        dump_backlog();
    #endif
    
        fprintf(stderr,"No Pike_error recovery context!\n%s",buf);
        exit(99);
      }
    
      if((size_t)strlen(buf) >= (size_t)sizeof(buf))
        fatal("Buffer overflow in Pike_error()\n");
      
      low_error(buf);
    }
    
    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))
    {
      int i;
    
      ASSERT_THREAD_SWAPPED_IN();
    
      if(in_error)
      {
        const char *tmp=in_error;
        in_error=0;
        fatal("Recursive Pike_error() calls, original Pike_error: %s",tmp);
      }
    
      in_error=text;
    
      if(!Pike_interpreter.recoveries)
      {
    #ifdef PIKE_DEBUG
        dump_backlog();
    #endif
    
        fprintf(stderr,"No Pike_error recovery context!\n%s():%s",name,text);
        if(file)
          fprintf(stderr,"at %s:%d\n",file,line);
        exit(99);
      }
    
      push_text(text);
    
      f_backtrace(0);
    
      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);
    
      f_aggregate(2);
    
      free_svalue(& throw_value);
      throw_value = *--Pike_sp;
      throw_severity=THROW_ERROR;
    
      in_error=0;
      pike_throw();  /* Hope someone is catching, or we will be out of balls. */
    }
    
    PMOD_EXPORT void exit_on_error(void *msg)
    {
      ONERROR tmp;
      SET_ONERROR(tmp,fatal_on_error,"Fatal in exit_on_error!");
      d_flag=0;
    
      fprintf(stderr,"%s\n",(char *)msg);
    #ifdef PIKE_DEBUG
      dump_backlog();
    #endif
      fprintf(stderr,"%s\n",(char *)msg);
    #ifdef PIKE_DEBUG
      {
        char *s;
        fprintf(stderr,"Attempting to dump raw Pike_error: (may fail)\n");
        init_buf();
        describe_svalue(&throw_value,0,0);
        s=simple_free_buf();
        fprintf(stderr,"%s\n",s);
        free(s);
      }
    #endif
      exit(1);
    }
    
    #ifdef __NT__
    /* Wrapper around abort() to avoid interactive requesters on NT. */
    static void do_abort()
    {
      if (!d_flag && !getenv("PIKE_DEBUG")) {
        exit(-6);	/* -SIGIOT */
      }
      abort();
    }
    #else /* !__NT__ */
    #define do_abort()	abort()
    #endif /* __NT__ */
    
    PMOD_EXPORT void fatal_on_error(void *msg)
    {
    #ifdef PIKE_DEBUG
      dump_backlog();
    #endif
      fprintf(stderr,"%s\n",(char *)msg);
      do_abort();
    }
    
    PMOD_EXPORT DECLSPEC(noreturn) void Pike_error(const char *fmt,...) ATTRIBUTE((noreturn,format (printf, 1, 2)))
    {
      va_list args;
      va_start(args,fmt);
      va_error(fmt,args);
      va_end(args);
    }
    
    PMOD_EXPORT DECLSPEC(noreturn) void debug_fatal(const char *fmt, ...) ATTRIBUTE((noreturn,format (printf, 1, 2)))
    {
      va_list args;
      static int in_fatal = 0;
    
      va_start(args,fmt);
      /* Prevent double fatal. */
      if (in_fatal)
      {
        (void)VFPRINTF(stderr, fmt, args);
        do_abort();
      }
    
      in_fatal = 1;
    #ifdef PIKE_DEBUG
      dump_backlog();
    #endif
    
      {
        extern int Pike_in_gc;
        if(Pike_in_gc)
        {
          fprintf(stderr,"Pike was in GC stage %d when this fatal occured:\n",Pike_in_gc);
          Pike_in_gc=0;
        }
      }
    
      (void)VFPRINTF(stderr, fmt, args);
    
      d_flag=t_flag=0;
      if(Pike_sp && Pike_interpreter.evaluator_stack)
      {
        fprintf(stderr,"Attempting to dump backlog (may fail)...\n");
        push_error("Backtrace at time of fatal:\n");
        APPLY_MASTER("describe_backtrace",1);
        if(Pike_sp[-1].type==PIKE_T_STRING)
          write_to_stderr(Pike_sp[-1].u.string->str, Pike_sp[-1].u.string->len);
      }else{
        fprintf(stderr,"No stack - no backtrace.\n");
      }
      fflush(stderr);
      do_abort();
    }
    
    #if 1
    
    #define ERR_DECLARE
    #include "errors.h"
    
    
    void f_error_cast(INT32 args)
    {
      char *s;
      get_all_args("Pike_error->cast",args,"%s",&s);
      if(!strncmp(s,"array",5))
      {
        pop_n_elems(args);
        ref_push_string(GENERIC_ERROR_THIS->desc);
        ref_push_array(GENERIC_ERROR_THIS->backtrace);
        f_aggregate(2);
      }else{
        SIMPLE_BAD_ARG_ERROR("Pike_error->cast", 1, "the value \"array\"");
      }
    }
    
    void f_error_index(INT32 args)
    {
      INT_TYPE ind;
      get_all_args("Pike_error->`[]",args,"%i",&ind);
    
      switch(ind)
      {
        case 0:
          pop_n_elems(args);
          ref_push_string(GENERIC_ERROR_THIS->desc);
          break;
        case 1:
          pop_n_elems(args);
          ref_push_array(GENERIC_ERROR_THIS->backtrace);
          break;
        default:
          index_error("Pike_error->`[]", Pike_sp-args, args, NULL, Pike_sp-args,
    		  "Index %d is out of range 0 - 1.\n", ind);
          break;
      }
    }
    
    
    void f_error_describe(INT32 args)
    {
      pop_n_elems(args);
      ref_push_object(Pike_fp->current_object);
      APPLY_MASTER("describe_backtrace",1);
    }
    
    void f_error_backtrace(INT32 args)
    {
      pop_n_elems(args);
      ref_push_array(GENERIC_ERROR_THIS->backtrace);
    }
    
    #ifdef ERROR_DEBUG
    #define DWERROR(X)	fprintf X
    #else /* !ERROR_DEBUG */
    #define DWERROR(X)
    #endif /* ERROR_DEBUG */
    
    #define INIT_ERROR(FEL)\
      va_list foo; \
      struct object *o; \
      va_start(foo,desc); \
      ASSERT_THREAD_SWAPPED_IN(); \
      o=low_clone(PIKE_CONCAT(FEL,_error_program)); \
      DWERROR((stderr, "%s(): Throwing a " #FEL " Pike_error\n", func))
    
    #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
    
    #define ERROR_COPY_SVALUE(STRUCT,X) do { \
        if (X) { \
          assign_svalue_no_free( & ERROR_STRUCT(STRUCT,o)->X, X); \
        } else { \
          ERROR_STRUCT(STRUCT, o)->X.type = PIKE_T_INT; \
          ERROR_STRUCT(STRUCT, o)->X.subtype = 0; \
          ERROR_STRUCT(STRUCT, o)->X.u.integer = 0; \
        } \
      } while (0)
    
    
    #define ERROR_COPY_REF(STRUCT,X) \
      add_ref( ERROR_STRUCT(STRUCT,o)->X=X )
    
    
    DECLSPEC(noreturn) void generic_error_va(struct object *o,
    					 char *func,
    					 struct svalue *base_sp,  int args,
    					 char *fmt,
    					 va_list foo)
         ATTRIBUTE((noreturn))
    {
      char buf[8192];
      struct pike_string *desc;
      struct array *backtrace;
      int i;
    
    #ifdef HAVE_VSNPRINTF
      vsnprintf(buf, sizeof(buf)-1, fmt, foo);
    #else /* !HAVE_VSNPRINTF */
      /* Sentinel that will be overwritten on buffer overflow. */
      buf[sizeof(buf)-1] = '\0';
    
      VSPRINTF(buf, fmt, foo);
    
      if(buf[sizeof(buf)-1])
        fatal("Buffer overflow in Pike_error()\n");
    #endif /* HAVE_VSNPRINTF */
      in_error=buf;
    
      if (!master_program) {
        fprintf(stderr, "ERROR: %s\n", buf);
      }
    
      ERROR_STRUCT(generic,o)->desc=make_shared_string(buf);
      f_backtrace(0);
    
      if(func)
      {
        push_int(0);
        push_int(0);
        push_text(func);
    
        for (i=0;i<args;i++)
          push_svalue(base_sp + i);
        f_aggregate(args + 3);
        f_aggregate(1);
        f_add(2);
      }
    
      if(Pike_sp[-1].type!=PIKE_T_ARRAY)
        fatal("Error failed to generate a backtrace!\n");
    
      ERROR_STRUCT(generic,o)->backtrace=Pike_sp[-1].u.array;
      Pike_sp--;
      dmalloc_touch_svalue(Pike_sp);
    
      free_svalue(& throw_value);
      throw_value.type=PIKE_T_OBJECT;
      throw_value.u.object=o;
      throw_severity = THROW_ERROR;
      in_error=0;
      pike_throw();  /* Hope someone is catching, or we will be out of balls. */
    }
    
    PMOD_EXPORT DECLSPEC(noreturn) void generic_error(
      char *func,
      struct svalue *base_sp,  int args,
      char *desc, ...) ATTRIBUTE((noreturn,format (printf, 4, 5)))
    {
      INIT_ERROR(generic);
      ERROR_DONE(generic);
    }
    
    PMOD_EXPORT DECLSPEC(noreturn) 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)))
    {
      INIT_ERROR(index);
      ERROR_COPY_SVALUE(index, val);
      ERROR_COPY_SVALUE(index, ind);
      ERROR_DONE(generic);
    }
    
    PMOD_EXPORT DECLSPEC(noreturn) 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)))
    {
      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{
        ERROR_STRUCT(bad_arg,o)->got.type=PIKE_T_INT;
        ERROR_STRUCT(bad_arg,o)->got.subtype=NUMBER_UNDEFINED;
        ERROR_STRUCT(bad_arg,o)->got.u.integer=0;
      }
      DWERROR((stderr, "%s():Bad arg %d (expected %s)\n",
    	   func, which_arg, expected_type));
      ERROR_DONE(generic);
    }
    
    PMOD_EXPORT DECLSPEC(noreturn) void math_error(
      char *func,
      struct svalue *base_sp,  int args,
      struct svalue *number,
      char *desc, ...) ATTRIBUTE((noreturn,format (printf, 5, 6)))
    {
      INIT_ERROR(math);
      if(number)
      {
        ERROR_COPY_SVALUE(math, number);
      }else{
        ERROR_STRUCT(math,o)->number.type=PIKE_T_INT;
        ERROR_STRUCT(math,o)->number.subtype=NUMBER_UNDEFINED;
        ERROR_STRUCT(math,o)->number.u.integer=0;
      }
      ERROR_DONE(generic);
    }
    
    PMOD_EXPORT DECLSPEC(noreturn) void resource_error(
      char *func,
      struct svalue *base_sp,  int args,
      char *resource_type,
      size_t howmuch_,
      char *desc, ...) ATTRIBUTE((noreturn,format (printf, 6, 7)))
    {
      INT_TYPE howmuch = DO_NOT_WARN((INT_TYPE)howmuch_);
      INIT_ERROR(resource);
      ERROR_COPY(resource, howmuch);
      ERROR_STRUCT(resource,o)->resource_type=make_shared_string(resource_type);
      ERROR_DONE(generic);
    }
    
    PMOD_EXPORT DECLSPEC(noreturn) void permission_error(
      char *func,
      struct svalue *base_sp, int args,
      char *permission_type,
      char *desc, ...) ATTRIBUTE((noreturn, format(printf, 5, 6)))
    {
      INIT_ERROR(permission);
      ERROR_STRUCT(permission,o)->permission_type=
        make_shared_string(permission_type);
      ERROR_DONE(generic);
    }
    
    PMOD_EXPORT void wrong_number_of_args_error(char *name, int args, int expected)
    {
      char *msg;
      if(expected>args)
      {
        msg="Too few arguments";
      }else{
        msg="Too many arguments";
      }
    
      new_error(name, msg, Pike_sp-args, args, 0,0);
    }
    
    #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
    
    void init_error(void)
    {
    #define ERR_SETUP
    #include "errors.h"
    
    #ifdef PIKE_DEBUG
      dmalloc_accept_leak(add_gc_callback(gc_check_throw_value,0,0));
    #endif
    }
    
    void cleanup_error(void)
    {
    #define ERR_CLEANUP
    #include "errors.h"
    }
    #endif