pike.git / src / error.c

version» Context lines:

pike.git/src/error.c:1:   /*   || 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. - || $Id$ +    */      #define NO_PIKE_SHORTHAND   #include "global.h"   #include "svalue.h"   #include "pike_macros.h"   #include "pike_error.h"   #include "interpret.h"   #include "stralloc.h"   #include "builtin_functions.h"   #include "array.h"   #include "mapping.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" -  + #include "pike_types.h"      /* __attribute__ only applies to function declarations, not    definitions, so we disable them here. */   #undef ATTRIBUTE   #define ATTRIBUTE(X)      /* #define ERROR_DEBUG */      PMOD_EXPORT const char msg_fatal_error[] = -  "%s:%d: Fatal error:\n"; +  "%s:%ld: 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";
pike.git/src/error.c:68: Inside #if defined(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 &&    Pike_interpreter.recoveries->on_stack &&    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)); +  (long)TESTILITEST);    fprintf(stderr, "Last recovery was added at %s:%d\n",    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();    Pike_fatal("Recoveries is out biking (Pike_interpreter.recoveries=%p, C sp=%p, %ld)!\n",    Pike_interpreter.recoveries, &foo, -  DO_NOT_WARN((long)TESTILITEST)); +  (long)TESTILITEST);    }       /* Add more stuff here when required */   }   #endif    -  + /*! @decl void _gdb_breakpoint() +  *! +  *! This function only exists so that it is possible to set a gdb +  *! breakpoint on the function pike_gdb_breakpoint. +  */   PMOD_EXPORT void pike_gdb_breakpoint(INT32 args)   {    pop_n_elems(args);   }      PMOD_EXPORT JMP_BUF *init_recovery(JMP_BUF *r, size_t stack_pop_levels DEBUG_INIT_REC_ARGS)   {    check_recovery_context();   #ifdef PIKE_DEBUG    r->file=location;
pike.git/src/error.c:118: Inside #if defined(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    return r;   }    + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void pike_throw(void) ATTRIBUTE((noreturn))   {   #ifdef TRACE_UNFINISHED_TYPE_FIELDS    accept_unfinished_type_fields++;   #endif       while(Pike_interpreter.recoveries && throw_severity > Pike_interpreter.recoveries->severity)    {    while(Pike_interpreter.recoveries->onerror)    {
pike.git/src/error.c:197: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if(Pike_sp - Pike_interpreter.evaluator_stack < Pike_interpreter.recoveries->stack_pointer)    Pike_fatal("Stack error in error.\n");   #endif       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;      #if defined(DEBUG_MALLOC) && defined(PIKE_DEBUG)    /* This will tell us where the value was caught (I hope) */ -  if(TYPEOF(throw_value) <= MAX_REF_TYPE) +  if(REFCOUNTED_TYPE(TYPEOF(throw_value)))    {    debug_malloc_update_location(throw_value.u.refs,    Pike_interpreter.recoveries->file);    debug_malloc_touch(throw_value.u.refs);    }   #endif      #ifdef TRACE_UNFINISHED_TYPE_FIELDS    accept_unfinished_type_fields--;   #endif
pike.git/src/error.c:231:   }      PMOD_EXPORT void push_error(const char *description)   {    push_text(description);    f_backtrace(0);    f_aggregate(2);   }      PMOD_EXPORT struct svalue throw_value = SVALUE_INIT_FREE; - int throw_severity; + PMOD_EXPORT int throw_severity;   static const char *in_error;    -  + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void low_error(const char *buf) ATTRIBUTE((noreturn))   {    push_error(buf);    free_svalue(& throw_value);    move_svalue (&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 va_make_error (const char *fmt, va_list args)   {    struct string_builder s;    init_string_builder(&s, 0);    string_builder_vsprintf(&s, fmt, args);    push_string(finish_string_builder(&s));    f_backtrace(0);    f_aggregate(2);   }    -  + /* coverity[+kill] */   PMOD_EXPORT void DECLSPEC(noreturn) va_error(const char *fmt, va_list args)    ATTRIBUTE((noreturn))   {    SWAP_IN_THREAD_IF_REQUIRED();    if(in_error)    {    const char *tmp=in_error;    in_error = NULL;    Pike_fatal("Recursive Pike_error() calls, "    "original error: %s, new error: %s", tmp, fmt);
pike.git/src/error.c:300:   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);   }    + /* coverity[+kill] */   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);   }    -  + /* coverity[+kill] */   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();
pike.git/src/error.c:363:    push_int(0);    push_int(0);    }       if (name)    push_text(name);    else    push_int(0);       for (i=-args; i; i++) { -  if (TYPEOF(oldsp[i]) <= PIKE_T_FLOAT) { +  if (TYPEOF(oldsp[i]) <= MAX_TYPE) {    push_svalue(oldsp + i);    } else {    char buffer[50];    sprintf(buffer, "<Svalue:0x%04x:0x%04x:%p>",    TYPEOF(oldsp[i]), SUBTYPEOF(oldsp[i]), oldsp[i].u.ptr);    push_text(buffer);    }    }       f_aggregate(args + 3);
pike.git/src/error.c:390:    free_svalue(&throw_value);    move_svalue (&throw_value, --Pike_sp);    throw_severity=THROW_ERROR;       in_error=0;    pike_throw(); /* Hope someone is catching, or we will be out of balls. */   }      static int inhibit_errors = 0;    + /* coverity[+kill] */   PMOD_EXPORT void exit_on_error(const void *msg)   {    ONERROR tmp;    SET_ONERROR(tmp,fatal_on_error,"Fatal in exit_on_error!");    d_flag=0;    Pike_interpreter.trace_level = 0;       if (inhibit_errors)    fprintf (stderr, "Got recursive error in exit_on_error: %s\n", (char *) msg);   
pike.git/src/error.c:463: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if (d_flag) {    fprintf(stderr,"%s\n",(char *)msg);    dump_backlog();    }   #endif    fprintf(stderr,"%s\n",(char *)msg);    do_abort();   }    + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void debug_va_fatal(const char *fmt, va_list args) ATTRIBUTE((noreturn))   {    static int in_fatal = 0;       /* fprintf(stderr, "Raw error: %s\n", fmt); */       /* Prevent double fatal. */    if (in_fatal)    { -  if (fmt) (void)VFPRINTF(stderr, fmt, args); +  if (fmt) (void)vfprintf(stderr, fmt, args);    do_abort();    }       in_fatal = 1;   #ifdef PIKE_DEBUG    if (d_flag) {   #ifdef HAVE_VA_COPY    if (fmt) {    va_list a;    va_copy (a, args); -  (void)VFPRINTF(stderr, fmt, a); +  (void)vfprintf(stderr, fmt, a);    va_end (a);    }   #endif    dump_backlog();    }   #endif    -  if (fmt) (void)VFPRINTF(stderr, fmt, args); +  if (fmt) (void)vfprintf(stderr, fmt, args);       if(Pike_in_gc)    fprintf(stderr,"Pike was in GC stage %d when this fatal occurred.\n",Pike_in_gc);    Pike_in_gc = GC_PASS_DISABLED;       d_flag=Pike_interpreter.trace_level=0;       if(Pike_sp && Pike_interpreter.evaluator_stack &&    master_object && master_object->prog)    {    JMP_BUF jmp;    struct callback_list saved_eval_cbs = evaluator_callbacks;    /* 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. */ -  + #ifdef PIKE_THREADS    threads_disabled++; -  MEMSET (&evaluator_callbacks, 0, sizeof (evaluator_callbacks)); + #endif +  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);    if(TYPEOF(Pike_sp[-1]) == PIKE_T_STRING)    write_to_stderr(Pike_sp[-1].u.string->str, Pike_sp[-1].u.string->len);    }    UNSETJMP (jmp); -  + #ifdef PIKE_THREADS    threads_disabled--; -  + #endif    evaluator_callbacks = saved_eval_cbs;    }else{    fprintf(stderr,"No stack - no backtrace.\n");    }    fflush(stderr);    do_abort();   }    -  + /* coverity[+kill] */   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);   }      #if 1   
pike.git/src/error.c:612:    *!    *! Cast operator.    *!    *! @note    *! The only supported type to cast to is @expr{"array"@}, which    *! generates an old-style error @expr{({@[message](),    *! @[backtrace]()})@}.    */   static void f_error_cast(INT32 args)   { -  char *s; -  get_all_args("error->cast",args,"%s",&s); -  if(!strncmp(s,"array",5)) +  if(Pike_sp[-args].u.string == literal_array_string)    { -  pop_n_elems(args); +  pop_stack();    apply_current (generic_err_message_fun, 0);    apply_current (generic_err_backtrace_fun, 0);    f_aggregate(2); -  }else{ -  SIMPLE_BAD_ARG_ERROR("error->cast", 1, "the value \"array\""); +     } -  +  else +  { +  pop_stack(); +  push_undefined();    } -  + }      /*! @decl array|string `[](int(0..1) index)    *!    *! Index operator.    *!    *! Simulates an array    *! @array    *! @elem string msg    *! Error message as returned by @[message].    *! @elem array backtrace
pike.git/src/error.c:646:    *!    *! @note    *! The error message is always terminated with a newline.    *!    *! @seealso    *! @[backtrace()]    */   static void f_error_index(INT32 args)   {    INT_TYPE ind; -  get_all_args("error->`[]",args,"%i",&ind); +  get_all_args("`[]",args,"%i",&ind);       switch(ind)    {    case 0:    pop_n_elems(args);    apply_current (generic_err_message_fun, 0);    break;    case 1:    pop_n_elems(args);    apply_current (generic_err_backtrace_fun, 0);    break;    default: -  index_error("error->`[]", Pike_sp-args, args, NULL, Pike_sp-args, +  index_error("`[]", Pike_sp-args, args, NULL, Pike_sp-args,    "Index %"PRINTPIKEINT"d is out of range 0..1.\n", ind);    break;    }   }    -  + 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); + } +    /*! @decl string describe()    *!    *! Return a readable error report that includes the backtrace.    */   static void f_error_describe(INT32 args)   {    pop_n_elems(args);    ref_push_object(Pike_fp->current_object);    APPLY_MASTER("describe_backtrace",1);   }
pike.git/src/error.c:748:    SEE_PRIVATE);    if (i != -1)    push_svalue (&PROG_FROM_INT (p, i)->    constants[ID_FROM_INT (p, i)->func.const_info.offset].sval);    else {    ref_push_program (p);    SAFE_APPLY_MASTER ("describe_program", 1);    }    }    -  push_constant_text("(%O)"); +  push_static_text("(%O)");    if(GENERIC_ERROR_THIS->error_message)    ref_push_string(GENERIC_ERROR_THIS->error_message);    else    push_int(0);    f_sprintf(2);    f_add(2);   }      /*! @decl int(0..1) _is_type(string t)    *!
pike.git/src/error.c:848:   #define ERROR_COPY_SVALUE(STRUCT,X) do { \    if (X) { \    assign_svalue_no_free( & ERROR_STRUCT(STRUCT,o)->X, X); \    } else { \    SET_SVAL(ERROR_STRUCT(STRUCT, o)->X, PIKE_T_INT, NUMBER_UNDEFINED, \    integer, 0); \    } \    } while (0)       - #define ERROR_COPY_REF(STRUCT,X) \ -  add_ref( ERROR_STRUCT(STRUCT,o)->X=X ) -  -  +    /* This prepares the passed object o, which is assumed to inherit    * generic_error_program, and throws it:    *    * o A backtrace is assigned to error_backtrace.    *    * 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.    *    * 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.)    */ -  + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void generic_error_va(    struct object *o, const char *func, const struct svalue *base_sp, int args,    const char *fmt, va_list *fmt_args)   { -  struct generic_error_struct *err = -  (struct generic_error_struct *) get_storage (o, generic_error_program); +  struct generic_error_struct *err = 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       if(in_error)    {    const char *tmp=in_error;    in_error=0;
pike.git/src/error.c:941:    pike_throw(); /* Hope someone is catching, or we will be out of balls. */   }         /* 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!    */ + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void throw_error_object(    struct object *o,    const char *func,    struct svalue *base_sp, int args,    const char *desc, ...) ATTRIBUTE((noreturn))   {    va_list foo;    va_start(foo,desc);    ASSERT_THREAD_SWAPPED_IN();    DWERROR((stderr, "%s(): Throwing an error object\n", func));    ERROR_DONE(generic);   }    -  + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void generic_error(    const char *func,    struct svalue *base_sp, int args,    const char *desc, ...) ATTRIBUTE((noreturn))   {    INIT_ERROR(generic);    ERROR_DONE(generic);   }    -  + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void index_error(    const char *func,    struct svalue *base_sp, int args,    struct svalue *value,    struct svalue *index,    const char *desc, ...) ATTRIBUTE((noreturn))   {    INIT_ERROR(index);    ERROR_COPY_SVALUE(index, value);    ERROR_COPY_SVALUE(index, index);    ERROR_DONE(generic);   }    -  + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void bad_arg_error(    const char *func,    struct svalue *base_sp, int args,    int which_argument,    const char *expected_type,    struct svalue *got_value,    const char *desc, ...) ATTRIBUTE((noreturn))   {    INIT_ERROR(bad_argument);    ERROR_COPY(bad_argument, which_argument);
pike.git/src/error.c:997:    ERROR_STRUCT(bad_argument,o)->expected_type =    make_shared_string(expected_type);    else    ERROR_STRUCT(bad_argument,o)->expected_type = NULL;    ERROR_COPY_SVALUE(bad_argument, got_value);    DWERROR((stderr, "%s():Bad arg %d (expected %s)\n",    func, which_argument, expected_type));    ERROR_DONE(generic);   }    + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void math_error(    const char *func,    struct svalue *base_sp, int args,    struct svalue *number,    const char *desc, ...) ATTRIBUTE((noreturn))   {    INIT_ERROR(math);    if(number)    {    ERROR_COPY_SVALUE(math, number);    }else{    SET_SVAL(ERROR_STRUCT(math,o)->number, PIKE_T_INT, NUMBER_UNDEFINED,    integer, 0);    }    ERROR_DONE(generic);   }    -  + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void resource_error(    const char *func,    struct svalue *base_sp, int args,    const char *resource_type,    size_t howmuch_,    const char *desc, ...) ATTRIBUTE((noreturn))   { -  INT_TYPE howmuch = DO_NOT_WARN((INT_TYPE)howmuch_); +  INT_TYPE howmuch = (INT_TYPE)howmuch_;    INIT_ERROR(resource);    ERROR_COPY(resource, howmuch);    ERROR_STRUCT(resource,o)->resource_type=make_shared_string(resource_type);    ERROR_DONE(generic);   }    -  + /* coverity[+kill] */   PMOD_EXPORT DECLSPEC(noreturn) void permission_error(    const char *func,    struct svalue *base_sp, int args,    const char *permission_type,    const char *desc, ...) ATTRIBUTE((noreturn))   {    INIT_ERROR(permission);    ERROR_STRUCT(permission,o)->permission_type=    make_shared_string(permission_type);    ERROR_DONE(generic);   }    -  + /* coverity[+kill] */   PMOD_EXPORT void wrong_number_of_args_error(const char *name, int args, int expected)   {    if(expected>args)    {    bad_arg_error (name, Pike_sp-args, args, expected, NULL, NULL,    "Too few arguments to %s(). Expected at least %d (got %d).\n",    name, expected, args);    }else {    bad_arg_error (name, Pike_sp-args, args, expected, NULL, NULL,    "Too many arguments to %s(). Expected at most %d (got %d).\n",    name, expected, args);    }   }      #ifdef PIKE_DEBUG - static void gc_check_throw_value(struct callback *foo, void *bar, void *gazonk) + static void gc_check_throw_value(struct callback *UNUSED(foo), void *UNUSED(bar), void *UNUSED(gazonk))   {    gc_mark_external_svalues(&throw_value,1," in the throw value");   }   #endif      void init_error(void)   {   #define ERR_SETUP   #include "errors.h"