|
|
|
|
|
|
#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" |
#include "sprintf.h" |
|
|
|
#undef ATTRIBUTE |
#define ATTRIBUTE(X) |
|
|
|
PMOD_EXPORT const char msg_fatal_error[] = |
"%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"; |
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_bad_arg_2[] = |
"Bad argument %d to %s(). %s\n"; |
PMOD_EXPORT const char msg_out_of_mem[] = |
"Out of memory.\n"; |
PMOD_EXPORT const char msg_out_of_mem_2[] = |
"Out of memory - failed to allocate %"PRINTSIZET"d bytes.\n"; |
PMOD_EXPORT const char msg_div_by_zero[] = |
"Division by zero.\n"; |
|
|
|
|
|
#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 && |
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, |
(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); |
|
|
|
pop_stack(); |
Pike_fatal("Recoveries is out biking (Pike_interpreter.recoveries=%p, C sp=%p, %ld)!\n", |
Pike_interpreter.recoveries, &foo, |
(long)TESTILITEST); |
} |
|
|
} |
#endif |
|
|
|
|
|
|
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; |
OED_FPRINTF((stderr, "init_recovery(%p) %s\n", r, location)); |
r->on_stack = on_stack; |
#endif |
r->frame_pointer=Pike_fp; |
r->stack_pointer=Pike_sp - stack_pop_levels - 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(); |
#ifdef PIKE_DEBUG |
|
|
|
|
|
|
#endif |
return r; |
} |
|
|
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) |
{ |
ONERROR *err = Pike_interpreter.recoveries->onerror; |
while(Pike_fp != err->frame_pointer) |
{ |
#ifdef PIKE_DEBUG |
if(!Pike_fp) |
Pike_fatal("Popped out of stack frames.\n"); |
#endif |
POP_PIKE_FRAME(); |
} |
|
Pike_interpreter.recoveries->onerror = err->previous; |
(*err->func)(err->arg); |
} |
|
{ |
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; |
} |
} |
|
if(!Pike_interpreter.recoveries) |
Pike_fatal("No error recovery context.\n"); |
|
|
|
|
|
while(Pike_interpreter.recoveries->onerror) |
{ |
ONERROR *err = Pike_interpreter.recoveries->onerror; |
|
while(Pike_fp != err->frame_pointer) |
{ |
#ifdef PIKE_DEBUG |
if(!Pike_fp) |
Pike_fatal("Popped out of stack frames.\n"); |
#endif |
POP_PIKE_FRAME(); |
} |
Pike_interpreter.recoveries->onerror = err->previous; |
(*err->func)(err->arg); |
} |
|
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(); |
} |
|
#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) |
|
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 |
|
if (Pike_interpreter.catch_ctx && |
&Pike_interpreter.catch_ctx->recovery == Pike_interpreter.recoveries) { |
|
|
#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); |
} |
|
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; |
PMOD_EXPORT 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); |
move_svalue (&throw_value, --Pike_sp); |
throw_severity = THROW_ERROR; |
in_error=0; |
pike_throw(); |
} |
|
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); |
} |
|
|
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); |
} |
|
in_error=fmt; |
|
if(!Pike_interpreter.recoveries) |
{ |
|
#ifdef PIKE_DEBUG |
if (d_flag) { |
fprintf(stderr,"No error recovery context!\n%s", fmt); |
dump_backlog(); |
} |
#endif |
|
fprintf(stderr,"No error recovery context!\n%s", fmt); |
exit(99); |
} |
|
va_make_error (fmt, args); |
free_svalue(&throw_value); |
move_svalue(&throw_value, --Pike_sp); |
throw_severity = THROW_ERROR; |
in_error = NULL; |
pike_throw(); |
} |
|
PMOD_EXPORT void make_error (const char *fmt, ...) |
|
|
{ |
va_list args; |
va_start (args,fmt); |
va_make_error (fmt,args); |
va_end (args); |
} |
|
|
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); |
} |
|
|
PMOD_EXPORT DECLSPEC(noreturn) void new_error(const char *name, |
const char *text, |
struct svalue *oldsp, |
INT32 args) ATTRIBUTE((noreturn)) |
{ |
int i; |
|
ASSERT_THREAD_SWAPPED_IN(); |
|
if(in_error) |
{ |
const char *tmp=in_error; |
in_error=0; |
Pike_fatal("Recursive error() calls, original error: %s",tmp); |
} |
|
in_error=text; |
|
if(!Pike_interpreter.recoveries) |
{ |
#ifdef PIKE_DEBUG |
if (d_flag) { |
fprintf(stderr,"No error recovery context!\n%s():%s", |
name ? name : "<unknown>", text); |
dump_backlog(); |
} |
#endif |
|
fprintf(stderr,"No error recovery context!\n%s():%s", |
name ? name : "<unknown>", text); |
exit(99); |
} |
|
push_text(text); |
|
f_backtrace(0); |
|
push_int(0); |
push_int(0); |
|
if (name) |
push_text(name); |
else |
push_int(0); |
|
for (i=-args; i; i++) { |
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); |
f_aggregate(1); |
|
f_add(2); |
|
f_aggregate(2); |
|
free_svalue(&throw_value); |
move_svalue (&throw_value, --Pike_sp); |
throw_severity=THROW_ERROR; |
|
in_error=0; |
pike_throw(); |
} |
|
static int inhibit_errors = 0; |
|
|
PMOD_EXPORT void exit_on_error(const void *msg) |
{ |
ONERROR tmp; |
|
if (throw_severity > THROW_ERROR) { |
|
|
|
|
return; |
} |
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); |
|
else { |
struct byte_buffer buf = BUFFER_INIT(); |
char *s; |
struct svalue thrown; |
|
inhibit_errors = 1; |
|
#ifdef PIKE_DEBUG |
if (d_flag) { |
fprintf(stderr,"%s\n",(char *)msg); |
dump_backlog(); |
} |
#endif |
|
fprintf(stderr,"%s\n",(char *)msg); |
|
|
|
Pike_interpreter.svalue_stack_margin = 0; |
Pike_interpreter.c_stack_margin = 0; |
fprintf(stderr,"Attempting to dump raw error: (may fail)\n"); |
move_svalue (&thrown, &throw_value); |
mark_free_svalue (&throw_value); |
describe_svalue(&buf, &thrown,0,0); |
free_svalue (&thrown); |
fprintf(stderr,"%s\n",buffer_get_string(&buf)); |
buffer_free(&buf); |
} |
|
exit(1); |
} |
|
#ifdef __NT__ |
|
int fnordel=0; |
static void do_abort() |
{ |
if (!d_flag && !getenv("PIKE_DEBUG")) { |
exit(-6); |
} |
fnordel=999/fnordel; |
} |
#else /* !__NT__ */ |
#define do_abort() abort() |
#endif /* __NT__ */ |
|
PMOD_EXPORT void fatal_on_error(const void *msg) |
{ |
|
if (throw_severity == THROW_EXIT) return; |
|
#ifdef PIKE_DEBUG |
if (d_flag) { |
fprintf(stderr,"%s\n",(char *)msg); |
dump_backlog(); |
} |
#endif |
fprintf(stderr,"%s\n",(char *)msg); |
do_abort(); |
} |
|
|
PMOD_EXPORT DECLSPEC(noreturn) void debug_va_fatal(const char *fmt, va_list args) ATTRIBUTE((noreturn)) |
{ |
static int in_fatal = 0; |
|
|
|
|
if (in_fatal) |
{ |
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); |
va_end (a); |
} |
#endif |
dump_backlog(); |
} |
#endif |
|
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; |
|
|
|
|
#ifdef PIKE_THREADS |
threads_disabled++; |
#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; |
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(); |
} |
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define GENERIC_ERROR_THIS ((struct generic_error_struct *)CURRENT_STORAGE) |
|
#define ERR_DECLARE |
#include "errors.h" |
|
|
|
|
|
|
|
|
|
|
static void f_error_cast(INT32 args) |
{ |
if(Pike_sp[-args].u.string == literal_array_string) |
{ |
pop_stack(); |
apply_current (generic_err_message_fun, 0); |
apply_current (generic_err_backtrace_fun, 0); |
f_aggregate(2); |
} |
else |
{ |
pop_stack(); |
push_undefined(); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void f_error_index(INT32 args) |
{ |
INT_TYPE 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("`[]", 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); |
} |
|
|
|
|
|
static void f_error_describe(INT32 args) |
{ |
pop_n_elems(args); |
ref_push_object(Pike_fp->current_object); |
APPLY_MASTER("describe_backtrace",1); |
} |
|
|
|
|
|
|
|
|
|
|
|
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); |
} |
|
|
|
|
|
|
|
|
|
static void f_error_backtrace(INT32 args) |
{ |
pop_n_elems(args); |
if(GENERIC_ERROR_THIS->error_backtrace) |
ref_push_array(GENERIC_ERROR_THIS->error_backtrace); |
else |
push_int(0); |
} |
|
|
|
static void f_error__sprintf(INT32 args) |
{ |
int mode = 0; |
|
if(args>0 && TYPEOF(Pike_sp[-args]) == PIKE_T_INT) |
mode = Pike_sp[-args].u.integer; |
pop_n_elems(args); |
|
if(mode != 'O') { |
push_undefined(); |
return; |
} |
|
{ |
struct program *p = Pike_fp->current_object->prog; |
int i; |
struct pike_string *error_name_str; |
|
|
|
|
|
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)-> |
constants[ID_FROM_INT (p, i)->func.const_info.offset].sval); |
else { |
ref_push_program (p); |
SAFE_APPLY_MASTER ("describe_program", 1); |
} |
} |
|
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); |
} |
|
|
|
|
|
|
static void f_error__is_type(INT32 args) |
{ |
struct pike_string *array_string; |
int ret; |
MAKE_CONST_STRING(array_string, "array"); |
if (args!=1) SIMPLE_WRONG_NUM_ARGS_ERROR("_is_type", 1); |
if (TYPEOF(Pike_sp[-args]) != PIKE_T_STRING) |
SIMPLE_ARG_TYPE_ERROR("_is_type", 1, "string"); |
ret = Pike_sp[-args].u.string == array_string; |
pop_n_elems(args); |
push_int(ret); |
} |
|
|
|
|
static void f_error_create(INT32 args) |
{ |
struct pike_string *msg; |
struct array *bt = NULL; |
|
get_all_args("create", args, "%W.%A", &msg, &bt); |
|
do_free_string(GENERIC_ERROR_THIS->error_message); |
copy_shared_string(GENERIC_ERROR_THIS->error_message, msg); |
|
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); |
} |
|
|
|
|
|
|
|
#ifdef ERROR_DEBUG |
#define DWERROR(...) fprintf(stderr, __VA_ARGS__) |
#else /* !ERROR_DEBUG */ |
#define DWERROR(...) |
#endif /* ERROR_DEBUG */ |
|
#define INIT_ERROR(FEL)\ |
va_list foo; \ |
struct object *o; \ |
va_start(foo,desc); \ |
ASSERT_THREAD_SWAPPED_IN(); \ |
DWERROR("%s(): Throwing a " #FEL " error\n", func); \ |
o=fast_clone_object(PIKE_CONCAT(FEL,_error_program)) |
|
#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 { \ |
SET_SVAL(ERROR_STRUCT(STRUCT, o)->X, PIKE_T_INT, NUMBER_UNDEFINED, \ |
integer, 0); \ |
} \ |
} while (0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 = 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_fatal("Recursive error() calls, original error: %s", tmp); |
} |
in_error = fmt ? fmt : "no error message"; |
|
if (fmt) { |
struct string_builder s; |
init_string_builder(&s, 0); |
string_builder_vsprintf(&s, fmt, *fmt_args); |
|
#if 0 |
if (!master_program) { |
fprintf(stderr, "ERROR: %s\n", s.s->str); |
} |
#endif |
|
if (err->error_message) free_string(err->error_message); |
err->error_message = finish_string_builder(&s); |
} |
|
f_backtrace(0); |
|
if(func) |
{ |
int i; |
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(TYPEOF(Pike_sp[-1]) != PIKE_T_ARRAY) |
Pike_fatal("f_backtrace failed to generate a backtrace!\n"); |
|
if (err->error_backtrace) free_array(err->error_backtrace); |
err->error_backtrace=Pike_sp[-1].u.array; |
Pike_sp--; |
dmalloc_touch_svalue(Pike_sp); |
|
free_svalue(& throw_value); |
SET_SVAL(throw_value, PIKE_T_OBJECT, 0, object, o); |
throw_severity = THROW_ERROR; |
in_error=0; |
|
dmalloc_touch_svalue(& throw_value); |
|
pike_throw(); |
} |
|
|
|
|
|
|
|
|
|
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("%s(): Throwing an error object\n", func); |
ERROR_DONE(generic); |
} |
|
|
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); |
} |
|
|
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); |
} |
|
|
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); |
if (expected_type) |
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("%s():Bad arg %d (expected %s)\n", |
func, which_argument, expected_type); |
ERROR_DONE(generic); |
} |
|
|
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); |
} |
|
|
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 = (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( |
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); |
} |
|
|
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 *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" |
|
#ifdef PIKE_DEBUG |
dmalloc_accept_leak(add_gc_callback(gc_check_throw_value,0,0)); |
|
|
#endif |
} |
|
void cleanup_error(void) |
{ |
#ifdef PIKE_DEBUG |
|
#endif |
#define ERR_CLEANUP |
#include "errors.h" |
} |
#endif |
|
|