pike.git
/
src
/
error.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/error.c:1:
-
/*
\
-
||
|
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.
-
\
*/
-
/**/
+
/*
+
|| 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.
+
*/
+
#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"
-
RCSID("$Id:
error.c,v
1.68
2001/01/12
02:15:56
mast
Exp
$");
-
+
/*
__attribute__ only applies to function declarations
,
not
+
definitions,
so
we disable them here. */
#undef ATTRIBUTE #define ATTRIBUTE(X)
-
/*
-
*
Backtrace
handling.
-
*/
+
/*
#define
ERROR_DEBUG
*/
-
struct
pike
_
backtrace
-
{
-
struct
pike
_
frame
*trace
;
-
struct
pike
_
frame
*iterator
;
-
int
iterator
_
index
;
-
}
;
+
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";
-
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
-
+
/* struct mapping *recovery_lookup = NULL; */
+
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) {
+
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)); 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",
+
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)); } /* Add more stuff here when required */ }
-
+
#endif
-
PMOD_EXPORT void pike_gdb_breakpoint(
void)
+
PMOD_EXPORT void pike_gdb_breakpoint(
INT32 args
)
{
-
+
pop_n_elems(args);
}
-
#endif
+
-
PMOD_EXPORT JMP_BUF *init_recovery(JMP_BUF *r DEBUG_
LINE
_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->
line=line;
-
r->
file=
file
;
-
OED_FPRINTF((stderr, "init_recovery(%p) %
s:%d\n
", r,
file, line
));
+
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-Pike_interpreter.evaluator_stack;
+
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
+
/* 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; } 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_interpreter.recoveries->onerror
->func)
(Pike_
interpreter.recoveries
->
onerror->arg
)
;
-
Pike_
interpreter.recoveries->onerror=
Pike_
interpreter
.
recoveries->onerror->previous
;
+
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=
Pike_interpreter.recoveries
->previous;
+
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)
-
fatal("No error recovery context.\n");
+
Pike_
fatal("No error recovery context.\n");
-
+
/* Don't pop the stack before the onerrors have run; they might need
+
* items from the stack.
+
*/
+
+
while(Pike_interpreter.recoveries->onerror)
+
{
+
ONERROR *err = Pike_interpreter.recoveries->onerror;
+
+
while(Pike_fp != err->frame_pointer)
+
{
#ifdef PIKE_DEBUG
-
if(Pike_sp
-
Pike_interpreter.evaluator_stack
<
Pike_
interpreter.recoveries->stack_pointer
)
-
fatal("
Stack
error
in
error
.\n");
+
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)
-
fatal("Popped out of stack frames.\n");
+
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;
-
while
(
Pike
_
interpreter.recoveries->onerror
)
+
#if
defined(DEBUG_MALLOC)
&& defined
(
PIKE
_
DEBUG
)
+
/* This will tell us where the value was caught (I hope) */
+
if(REFCOUNTED_TYPE(TYPEOF(throw_value)))
{
-
(
*Pike
_
interpreter
.
recoveries->onerror->func)(
Pike_interpreter.recoveries->
onerror->arg
);
-
Pike
_
interpreter.recoveries->onerror=Pike
_
interpreter
.
recoveries->onerror->previous
;
+
debug_malloc_update_location
(
throw
_
value
.
u.refs,
+
Pike_interpreter.recoveries->
file
);
+
debug
_
malloc
_
touch(throw_value
.
u.refs)
;
}
-
+
#endif
-
longjmp
(Pike_interpreter.
recoveries
->recovery,1);
+
#ifdef
TRACE_UNFINISHED_TYPE_FIELDS
+
accept_unfinished_type_fields--;
+
#endif
+
+
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);
+
}
PMOD_EXPORT void push_error(const char *description) { push_text(description); f_backtrace(0); f_aggregate(2); }
-
PMOD_EXPORT struct svalue throw_value =
{ PIKE
_
T
_
INT }
;
+
PMOD_EXPORT struct svalue throw_value =
SVALUE
_
INIT
_
FREE
;
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;
+
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. */ }
-
/*
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))
+
PMOD_EXPORT
void va_
make_
error
(const char *fmt, va_list args)
{
-
char
buf[4096]
;
+
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=
0
;
-
fatal("Recursive error() calls, original error: %s",tmp);
+
in_error
=
NULL
;
+
Pike_
fatal("Recursive
Pike_
error() calls,
"
+
"
original error: %s
, new error: %s
",
tmp
, fmt
);
}
-
in_error=
buf
;
+
in_error=
fmt
;
-
#ifdef HAVE_VSNPRINTF
-
vsnprintf(buf, 4090, fmt, args);
-
#else /* !HAVE_VSNPRINTF */
-
VSPRINTF(buf, fmt, args);
-
#endif /* HAVE_VSNPRINTF */
-
+
if(!Pike_interpreter.recoveries) {
-
+
/* FIXME: Why not use Pike_fatal() here? */
#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",
buf
);
+
fprintf(stderr,"No error recovery context!\n%s",
fmt
);
exit(99); }
-
if((size
_
t)strlen
(
buf
)
>=
(
size
_
t
)
sizeof
(
buf
)
)
-
fatal("Buffer
overflow
in
error()
\n")
;
+
va
_
make_error
(
fmt, args
)
;
+
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. */
+
}
-
low
_error(
buf
);
+
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);
}
-
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))
+
/* 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);
+
}
+
+
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 error() calls, original error: %s",tmp);
+
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,text);
+
fprintf(stderr,"No error recovery context!\n%s():%s",
+
name
? name : "<unknown>"
,
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); }
-
+
+
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);
-
throw_value
= *
--Pike_sp;
+
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 exit_on_error(void *msg)
+
static int inhibit_errors = 0;
+
+
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;
-
fprintf(stderr,"%s\n",(char *)msg);
+
if (inhibit_errors)
+
fprintf
(stderr,
"
Got recursive error in exit_on_error:
%s\n",
(char *)
msg);
+
+
else {
+
dynamic_buffer save_buf;
+
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);
-
#ifdef
PIKE
_
DEBUG
-
{
-
char
*
s
;
+
+
/* 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;
fprintf(stderr,"Attempting to dump raw error: (may fail)\n");
-
init_buf();
-
describe
_svalue(&throw_value,0,0);
-
s=simple_free_buf();
+
init_buf(
&save_buf
);
+
move
_svalue
(&
thrown, &
throw_value
);
+
mark_free_svalue (&throw_value);
+
describe_svalue(&thrown
,0,0);
+
free_svalue (&thrown);
+
s=simple_free_buf(
&save_buf
);
fprintf(stderr,"%s\n",s); free(s); }
-
#endif
+
exit(1); } #ifdef __NT__ /* Wrapper around abort() to avoid interactive requesters on NT. */
-
+
int fnordel=0;
static void do_abort() { if (!d_flag && !getenv("PIKE_DEBUG")) { exit(-6); /* -SIGIOT */ }
-
abort()
;
+
fnordel=999/fnordel
;
} #else /* !__NT__ */ #define do_abort() abort() #endif /* __NT__ */
-
PMOD_EXPORT void fatal_on_error(void *msg)
+
PMOD_EXPORT void fatal_on_error(
const
void *msg)
{
-
+
/* It's ok if we're exiting. */
+
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
Pike
_
error
(const char *fmt,
...
) ATTRIBUTE((noreturn
,format (printf, 1, 2
))
)
+
PMOD_EXPORT DECLSPEC(noreturn) void
debug
_
va_fatal
(const char *fmt,
va_list args
) ATTRIBUTE((noreturn))
{
-
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);
+
/* fprintf
(
stderr
,
"Raw error: %s\n",
fmt);
*/
+
/* Prevent double fatal. */ if (in_fatal) {
-
(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);
+
va_end (a);
+
}
+
#endif
dump_backlog();
-
+
}
#endif
-
{
-
extern int Pike_in_gc
;
+
if
(fmt)
(void)VFPRINTF(stderr,
fmt,
args)
;
+
if(Pike_in_gc)
-
{
-
fprintf(stderr,"Pike was in GC stage %d when this fatal
occured:
\n",Pike_in_gc);
-
Pike_in_gc=
0;
-
}
-
}
+
fprintf(stderr,"Pike was in GC stage %d when this fatal
occurred.
\n",Pike_in_gc);
+
Pike_in_gc
=
GC_PASS_DISABLED
;
-
(void)VFPRINTF(stderr, fmt, args)
;
+
d_flag=Pike_interpreter.trace_level=0
;
-
d_flag=t_flag=0;
-
if(Pike_sp && Pike_interpreter.evaluator_stack)
+
if(Pike_sp && Pike_interpreter.evaluator_stack
&&
+
master_object && master_object->prog
)
{
-
fprintf(stderr,"
Attempting
to
dump
backlog
(may
fail)
.
..
\n");
+
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++;
+
#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(Pike_sp[-1]
.type
==PIKE_T_STRING)
+
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
-
+
/*! @class MasterObject
+
*/
+
+
/*! @decl string describe_backtrace(mixed exception)
+
*!
+
*! Called by various routines to format a readable
+
*! description of an exception.
+
*!
+
*! @param exception
+
*! Something that was thrown. Usually an @[Error.Generic] object, or
+
*! 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
+
*/
+
+
/*! @module Error
+
*/
+
+
/*! @class Generic
+
*! Class for exception objects for errors of unspecified type.
+
*/
+
+
/*! @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.
+
*/
+
+
#define GENERIC_ERROR_THIS ((struct generic_error_struct *)CURRENT_STORAGE)
+
#define ERR_DECLARE #include "errors.h"
-
-
void f_error_cast(INT32 args)
+
/*! @decl array cast(string type)
+
*!
+
*! 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)) { pop_n_elems(args);
-
ref
_
push_string
(
GENERIC
_
ERROR
_
THIS->desc
);
-
ref
_
push_array
(
GENERIC
_
ERROR
_
THIS->
backtrace);
+
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\""); } }
-
void f_error_index(INT32 args)
+
/*! @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
+
*! Backtrace as returned by @[backtrace].
+
*! @endarray
+
*!
+
*! @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); switch(ind) { case 0: pop_n_elems(args);
-
ref
_
push_string
(
GENERIC
_
ERROR
_
THIS->desc
);
+
apply
_
current
(
generic
_
err
_
message_fun, 0
);
break; case 1: pop_n_elems(args);
-
ref
_
push_array
(
GENERIC
_
ERROR
_
THIS->
backtrace);
+
apply
_
current
(
generic
_
err
_backtrace
_fun, 0
);
break; default: index_error("error->`[]", Pike_sp-args, args, NULL, Pike_sp-args,
-
"Index %d is out of range 0
-
1.\n", ind);
+
"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);
+
}
-
void f_error_
describe
(INT32 args)
+
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); }
-
void f_error_
backtrace
(INT32 args)
+
/*! @decl string message()
+
*!
+
*! 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.
+
*/
+
static
void f_error_
message
(INT32 args)
{ pop_n_elems(args);
-
ref_push_
array
(GENERIC_ERROR_THIS->
backtrace
);
+
if (GENERIC_ERROR_THIS->error_message)
+
ref_push_
string
(GENERIC_ERROR_THIS->
error_message
);
+
else
+
push_int (0);
}
-
+
/*! @decl array backtrace()
+
*!
+
*! Return the backtrace where the error occurred. Normally simply
+
*! returns @[error_backtrace].
+
*!
+
*! @seealso
+
*! @[predef::backtrace()]
+
*/
+
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);
+
}
+
+
/*! @decl string _sprintf()
+
*/
+
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;
+
/* 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)->
+
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)");
+
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)
+
*!
+
*! Claims that the error object is an array, for compatibility with
+
*! old style error handling code.
+
*/
+
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);
+
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);
+
}
+
+
/*! @decl void create(string message, @
+
*! void|array(backtrace_frame|array(mixed)) backtrace)
+
*/
+
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);
+
}
+
+
/*! @endclass
+
*/
+
+
/*! @endmodule
+
*/
+
#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 " error\n", func))
+
DWERROR((stderr, "%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)); \
+
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; \
+
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 )
-
DECLSPEC(noreturn)
void
generic_error_va(struct
object
*
o,
-
char
*
func,
-
struct svalue *base
_
sp,
int
args
,
-
char *fmt,
-
va_list
foo
)
-
ATTRIBUTE((noreturn))
+
/*
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.)
+
*/
+
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
)
{
-
char buf[8192];
-
struct
pike
_
string
*
desc;
-
struct
array
*
backtrace;
-
int
i
;
+
struct
generic
_
error_struct
*
err =
+
(
struct
generic_error_struct
*
)
get_storage
(o,
generic_error_program)
;
-
#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'
;
+
#ifdef
PIKE
_
DEBUG
+
if
(
!err
)
+
Pike
_
fatal
("Got
an
object
which
doesn't
inherit
generic_error_program
.
\n"
);
+
#endif
-
VSPRINTF
(
buf
,
fmt
,
foo
);
+
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(
buf[sizeof(buf
)
-1])
-
fatal("Buffer
overflow
in
error
()
\n")
;
-
#endif
/*
HAVE_VSNPRINTF
*/
-
in
_
error=buf
;
+
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",
buf
);
+
fprintf(stderr, "ERROR: %s\n",
s.s->str
);
}
-
+
#endif
-
ERROR
_
STRUCT
(
generic,o
)->
desc
=
make
_
shared_
string(
buf
);
+
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(Pike_sp[-1]
.type
!=PIKE_T_ARRAY)
-
fatal("
Error
failed to generate a backtrace!\n");
+
if(
TYPEOF(
Pike_sp[-1]
)
!=
PIKE_T_ARRAY)
+
Pike_
fatal("
f_backtrace
failed to generate a backtrace!\n");
-
ERROR
_
STRUCT
(
generic,o
)->backtrace=Pike_sp[-1].u.array;
+
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);
-
throw_value
.type=
PIKE_T_OBJECT
;
-
throw_value.u.
object
=
o;
+
SET_SVAL(
throw_value
,
PIKE_T_OBJECT
,
0,
object
,
o
)
;
throw_severity = THROW_ERROR; in_error=0;
-
+
+
dmalloc_touch_svalue(& throw_value);
+
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!
+
*/
+
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);
+
}
+
PMOD_EXPORT DECLSPEC(noreturn) void generic_error(
-
char *func,
+
const
char *func,
struct svalue *base_sp, int args,
-
char *desc, ...) ATTRIBUTE((noreturn
,format (printf, 4, 5
))
)
+
const
char *desc, ...) ATTRIBUTE((noreturn))
{ INIT_ERROR(generic); ERROR_DONE(generic); } PMOD_EXPORT DECLSPEC(noreturn) void index_error(
-
char *func,
+
const
char *func,
struct svalue *base_sp, int args,
-
struct svalue *
val
,
-
struct svalue *
ind
,
-
char *desc, ...) ATTRIBUTE((noreturn
,format (printf, 6, 7
))
)
+
struct svalue *
value
,
+
struct svalue *
index
,
+
const
char *desc, ...) ATTRIBUTE((noreturn))
{ INIT_ERROR(index);
-
ERROR_COPY_SVALUE(index,
val
);
-
ERROR_COPY_SVALUE(index,
ind
);
+
ERROR_COPY_SVALUE(index,
value
);
+
ERROR_COPY_SVALUE(index,
index
);
ERROR_DONE(generic); } PMOD_EXPORT DECLSPEC(noreturn) void bad_arg_error(
-
char *func,
+
const
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
))
)
+
int which_
argument
,
+
const
char *expected_type,
+
struct svalue *got
_value
,
+
const
char *desc, ...) ATTRIBUTE((noreturn))
{
-
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
;
-
}
+
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((stderr, "%s():Bad arg %d (expected %s)\n",
-
func, which_
arg
, expected_type));
+
func, which_
argument
, expected_type));
ERROR_DONE(generic); } PMOD_EXPORT DECLSPEC(noreturn) void math_error(
-
char *func,
+
const
char *func,
struct svalue *base_sp, int args, struct svalue *number,
-
char *desc, ...) ATTRIBUTE((noreturn
,format (printf, 5, 6
))
)
+
const
char *desc, ...) ATTRIBUTE((noreturn))
{ 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;
+
SET_SVAL(
ERROR_STRUCT(math,o)->number
,
PIKE_T_INT
,
NUMBER_UNDEFINED
,
+
integer
,
0
);
} ERROR_DONE(generic); } PMOD_EXPORT DECLSPEC(noreturn) void resource_error(
-
char *func,
+
const
char *func,
struct svalue *base_sp, int args,
-
char *resource_type,
+
const
char *resource_type,
size_t howmuch_,
-
char *desc, ...) ATTRIBUTE((noreturn
,format (printf, 6, 7
))
)
+
const
char *desc, ...) ATTRIBUTE((noreturn))
{ 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,
+
const
char *func,
struct svalue *base_sp, int args,
-
char *permission_type,
-
char *desc, ...) ATTRIBUTE((noreturn
, format(printf, 5, 6
))
)
+
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(char *name, int args, int expected)
+
PMOD_EXPORT void wrong_number_of_args_error(
const
char *name, int args, int expected)
{
-
char *msg;
+
if(expected>args) {
-
msg=
"Too few arguments";
-
}else{
-
msg=
"Too many arguments";
+
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)
;
}
-
-
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");
+
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));
-
+
+
/* recovery_lookup = allocate_mapping(100); */
#endif } void cleanup_error(void) {
-
+
#ifdef PIKE_DEBUG
+
/* free_mapping(recovery_lookup); */
+
#endif
#define ERR_CLEANUP #include "errors.h" } #endif