summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-04-16 14:16:33 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-04-16 14:16:33 -0700
commitf029f2815c2d69ef833089f476d32cadc5edd2de (patch)
tree2fa684767bf49a32eca8c0eb9c5a8690ad620c1d
parenta46ef5d5b56f0ca6f69a36ddf131bc3b9658b758 (diff)
downloadtxr-f029f2815c2d69ef833089f476d32cadc5edd2de.tar.gz
txr-f029f2815c2d69ef833089f476d32cadc5edd2de.tar.bz2
txr-f029f2815c2d69ef833089f476d32cadc5edd2de.zip
cmdline: use handler instead of catch for errors.
Errors encountered when parsing or evaluating a source file should be handled using a handler rather than a catch, so that the unwind stack is available to the error reporting function. This anticipates being able to dump a backtrace. * txr.c (parse_once_noerr, read_eval_stream_noerr): Adjust to reduced argument count in ignerr_func_body macro. * unwind.c (uw_trace_error): New function. * unwind.h (uw_trace_error): Declared. (ignerr_func_body): Revised to establish a handler in addition to the catch. The catch now doesn't do anything other than provide an intercepting exit point; the error_trace call is moved into the handler, and so it executes in a context where unwinding hasn't happened yet.
-rw-r--r--txr.c5
-rw-r--r--unwind.c7
-rw-r--r--unwind.h17
3 files changed, 21 insertions, 8 deletions
diff --git a/txr.c b/txr.c
index dab0b7f5..5e5f7999 100644
--- a/txr.c
+++ b/txr.c
@@ -472,15 +472,14 @@ static void no_dbg_support(val arg)
static int parse_once_noerr(val stream, val name, parser_t *parser)
{
val pfx = format(nil, lit("~a:"), name, nao);
- ignerr_func_body(int, 0, parse_once(stream, name, parser),
- exsym, exargs, std_error, pfx);
+ ignerr_func_body(int, 0, parse_once(stream, name, parser), std_error, pfx);
}
static val read_eval_stream_noerr(val self, val stream, val name, val error_stream)
{
val pfx = format(nil, lit("~a:"), name, nao);
ignerr_func_body(val, nil, read_eval_stream(self, stream, error_stream),
- exsym, exargs, std_error, pfx);
+ std_error, pfx);
}
int txr_main(int argc, char **argv)
diff --git a/unwind.c b/unwind.c
index f3a4df24..5d24e6ce 100644
--- a/unwind.c
+++ b/unwind.c
@@ -422,6 +422,13 @@ val uw_muffle_warning(val exc, struct args *args)
uw_throw(continue_s, nil);
}
+val uw_trace_error(val ctx, val exc, struct args *args)
+{
+ cons_bind (stream, prefix, ctx);
+ error_trace(exc, args_get_list(args), stream, prefix);
+ return nil;
+}
+
void uw_push_cont_copy(uw_frame_t *fr, mem_t *ptr,
void (*copy)(mem_t *ptr, int parent))
{
diff --git a/unwind.h b/unwind.h
index 0dfeea17..edf079ee 100644
--- a/unwind.h
+++ b/unwind.h
@@ -145,6 +145,7 @@ val uw_find_frame(val extype, val frtype);
val uw_find_frames(val extype, val frtype);
val uw_invoke_catch(val catch_frame, val sym, struct args *);
val uw_muffle_warning(val exc, struct args *);
+val uw_trace_error(val ctx, val exc, struct args *);
val uw_capture_cont(val tag, val fun, val ctx_form);
void uw_push_cont_copy(uw_frame_t *, mem_t *ptr,
void (*copy)(mem_t *ptr, int parent));
@@ -274,13 +275,19 @@ noreturn val type_mismatch(val, ...);
#EXPR \
" failed")
-#define ignerr_func_body(type, init, expr, exsym, \
- exargs, stream, prefix) \
+#define ignerr_func_body(type, init, expr, \
+ stream, prefix) \
+ val (_s_y_m_s) = cons(error_s, nil); \
type (_r_e_t) = (init); \
- uw_catch_begin (cons(error_s, nil), exsym, exargs); \
+ uw_frame_t _h_n_d; \
+ uw_catch_begin (_s_y_m_s, _e_x, _e_x_a); \
+ uw_push_handler(&_h_n_d, _s_y_m_s, \
+ func_f1v(cons(stream, prefix), \
+ uw_trace_error)); \
_r_e_t = expr; \
- uw_catch(exsym, exargs) \
- error_trace(exsym, exargs, stream, prefix); \
+ uw_pop_frame(&_h_n_d); \
+ uw_catch(_e_x, _e_x_a); \
+ (void) _e_x_a; \
uw_unwind { } \
uw_catch_end; \
return _r_e_t;