diff --git a/src/error.c b/src/error.c index ff11cf96f2118618d465bfc78b74aadd417d7978..68179b540d930b9dadb76588f3803de97cd758ab 100644 --- a/src/error.c +++ b/src/error.c @@ -21,19 +21,218 @@ #include "threads.h" #include "gc.h" -RCSID("$Id: error.c,v 1.57 2000/08/10 09:51:51 per Exp $"); +RCSID("$Id: error.c,v 1.58 2000/08/15 11:04:52 grubba 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) - fatal("Recoveries is out biking (Pike_interpreter.recoveries=%p, Pike_sp=%p, %d)!\n",Pike_interpreter.recoveries, &foo,TESTILITEST); + if(Pike_interpreter.recoveries && TESTILITEST > 0) { + fprintf(stderr, "Recoveries is out biking (Pike_interpreter.recoveries=%p, Pike_sp=%p, %d)!\n", + Pike_interpreter.recoveries, &foo, 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, %d)!\n", + Pike_interpreter.recoveries, &foo, TESTILITEST); + } /* Add more stuff here when required */ } @@ -432,6 +631,10 @@ void generic_error_va(struct object *o, #endif /* HAVE_VSNPRINTF */ in_error=buf; + if (1 || !master_program) { + fprintf(stderr, "ERROR: %s\n", buf); + } + ERROR_STRUCT(generic,o)->desc=make_shared_string(buf); f_backtrace(0); @@ -531,7 +734,7 @@ PMOD_EXPORT void resource_error( char *func, struct svalue *base_sp, int args, char *resource_type, - long howmuch, + size_t howmuch, char *desc, ...) ATTRIBUTE((noreturn,format (printf, 6, 7))) { INIT_ERROR(resource);