baggage. */
-#define CACHE_VAR(var,name) \
- static SCM var = SCM_BOOL_F; \
- if (scm_is_false (var)) \
- { \
- var = scm_module_variable (scm_the_root_module (), \
- scm_from_locale_symbol (name)); \
- if (scm_is_false (var)) \
- abort (); \
- }
-
\f
+static SCM catch_var, throw_var, with_throw_handler_var;
+
SCM
scm_catch (SCM key, SCM thunk, SCM handler)
{
- CACHE_VAR (var, "catch");
-
- return scm_call_3 (scm_variable_ref (var), key, thunk, handler);
+ return scm_call_3 (scm_variable_ref (catch_var), key, thunk, handler);
}
SCM
if (SCM_UNBNDP (pre_unwind_handler))
return scm_catch (key, thunk, handler);
else
- {
- CACHE_VAR (var, "catch");
-
- return scm_call_4 (scm_variable_ref (var), key, thunk, handler,
- pre_unwind_handler);
- }
+ return scm_call_4 (scm_variable_ref (catch_var), key, thunk, handler,
+ pre_unwind_handler);
+}
+
+static void
+init_with_throw_handler_var (void)
+{
+ with_throw_handler_var
+ = scm_module_variable (scm_the_root_module (),
+ scm_from_latin1_symbol ("with-throw-handler"));
}
SCM
scm_with_throw_handler (SCM key, SCM thunk, SCM handler)
{
- CACHE_VAR (var, "with-throw-handler");
+ static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
+ scm_i_pthread_once (&once, init_with_throw_handler_var);
- return scm_call_3 (scm_variable_ref (var), key, thunk, handler);
+ return scm_call_3 (scm_variable_ref (with_throw_handler_var),
+ key, thunk, handler);
}
SCM
scm_throw (SCM key, SCM args)
{
- CACHE_VAR (var, "throw");
-
- return scm_apply_1 (scm_variable_ref (var), key, args);
+ return scm_apply_1 (scm_variable_ref (throw_var), key, args);
}
\f
}
+static int
+should_print_backtrace (SCM tag, SCM stack)
+{
+ return SCM_BACKTRACE_P
+ && scm_is_true (stack)
+ && scm_initialized_p
+ /* It's generally not useful to print backtraces for errors reading
+ or expanding code in these fallback catch statements. */
+ && !scm_is_eq (tag, scm_from_latin1_symbol ("read-error"))
+ && !scm_is_eq (tag, scm_from_latin1_symbol ("syntax-error"));
+}
+
static void
handler_message (void *handler_data, SCM tag, SCM args)
{
- char *prog_name = (char *) handler_data;
- SCM p = scm_current_error_port ();
-
- if (scm_is_eq (tag, scm_from_latin1_symbol ("syntax-error"))
- && scm_ilength (args) >= 5)
+ SCM p, stack, frame;
+
+ p = scm_current_error_port ();
+ /* Usually we get here via a throw to a catch-all. In that case
+ there is the throw frame active, and the catch closure, so narrow by
+ two frames. It is possible for a user to invoke
+ scm_handle_by_message directly, though, so it could be this
+ narrows too much. We'll have to see how this works out in
+ practice. */
+ stack = scm_make_stack (SCM_BOOL_T, scm_list_1 (scm_from_int (2)));
+ frame = scm_is_true (stack) ? scm_stack_ref (stack, SCM_INUM0) : SCM_BOOL_F;
+
+ if (should_print_backtrace (tag, stack))
{
- SCM who = SCM_CAR (args);
- SCM what = SCM_CADR (args);
- SCM where = SCM_CADDR (args);
- SCM form = SCM_CADDDR (args);
- SCM subform = SCM_CAR (SCM_CDDDDR (args));
-
- scm_puts ("Syntax error:\n", p);
-
- if (scm_is_true (where))
- {
- SCM file, line, col;
-
- file = scm_assq_ref (where, scm_sym_filename);
- line = scm_assq_ref (where, scm_sym_line);
- col = scm_assq_ref (where, scm_sym_column);
-
- if (scm_is_true (file))
- scm_display (file, p);
- else
- scm_puts ("unknown file", p);
- scm_puts (":", p);
- scm_display (line, p);
- scm_puts (":", p);
- scm_display (col, p);
- scm_puts (": ", p);
- }
- else
- scm_puts ("unknown location: ", p);
-
- if (scm_is_true (who))
- {
- scm_display (who, p);
- scm_puts (": ", p);
- }
-
- scm_display (what, p);
-
- if (scm_is_true (subform))
- {
- scm_puts (" in subform ", p);
- scm_write (subform, p);
- scm_puts (" of ", p);
- scm_write (form, p);
- }
- else if (scm_is_true (form))
- {
- scm_puts (" in form ", p);
- scm_write (form, p);
- }
-
+ scm_puts ("Backtrace:\n", p);
+ scm_display_backtrace_with_highlights (stack, p,
+ SCM_BOOL_F, SCM_BOOL_F,
+ SCM_EOL);
scm_newline (p);
}
- else if (scm_ilength (args) == 4)
- {
- SCM stack = scm_make_stack (SCM_BOOL_T, SCM_EOL);
- SCM subr = SCM_CAR (args);
- SCM message = SCM_CADR (args);
- SCM parts = SCM_CADDR (args);
- SCM rest = SCM_CADDDR (args);
-
- if (SCM_BACKTRACE_P && scm_is_true (stack) && scm_initialized_p)
- {
- SCM highlights;
-
- if (scm_is_eq (tag, scm_arg_type_key)
- || scm_is_eq (tag, scm_out_of_range_key))
- highlights = rest;
- else
- highlights = SCM_EOL;
-
- scm_puts ("Backtrace:\n", p);
- scm_display_backtrace_with_highlights (stack, p,
- SCM_BOOL_F, SCM_BOOL_F,
- highlights);
- scm_newline (p);
- }
- scm_i_display_error (scm_is_true (stack)
- ? scm_stack_ref (stack, SCM_INUM0) : SCM_BOOL_F,
- p, subr, message, parts, rest);
- }
- else
- {
- if (! prog_name)
- prog_name = "guile";
-
- scm_puts (prog_name, p);
- scm_puts (": ", p);
- scm_puts ("uncaught throw to ", p);
- scm_prin1 (tag, p, 0);
- scm_puts (": ", p);
- scm_prin1 (args, p, 1);
- scm_putc ('\n', p);
- }
+ scm_print_exception (p, frame, tag, args);
}
}
SCM
-scm_ithrow (SCM key, SCM args, int noreturn SCM_UNUSED)
+scm_ithrow (SCM key, SCM args, int no_return SCM_UNUSED)
{
return scm_throw (key, args);
}
if (SCM_PROMPT_SETJMP (prompt))
{
/* nonlocal exit */
- SCM args = scm_i_prompt_pop_abort_args_x (prompt);
+ SCM args = scm_i_prompt_pop_abort_args_x (vm);
/* cdr past the continuation */
return scm_apply_0 (handler, scm_cdr (args));
}
return scm_at_abort (sym_pre_init_catch_tag, scm_cons (k, args));
else
{
- fprintf (stderr, "Throw without catch before boot:\n");
- scm_handle_by_message_noexit (NULL, k, args);
+ static int error_printing_error = 0;
+ static int error_printing_fallback = 0;
+
+ if (error_printing_fallback)
+ fprintf (stderr, "\nFailed to print exception.\n");
+ else if (error_printing_error)
+ {
+ fprintf (stderr, "\nError while printing exception:\n");
+ error_printing_fallback = 1;
+ fprintf (stderr, "Key: ");
+ scm_write (k, scm_current_error_port ());
+ fprintf (stderr, ", args: ");
+ scm_write (args, scm_current_error_port ());
+ scm_newline (scm_current_error_port ());
+ }
+ else
+ {
+ fprintf (stderr, "Throw without catch before boot:\n");
+ error_printing_error = 1;
+ scm_handle_by_message_noexit (NULL, k, args);
+ }
+
fprintf (stderr, "Aborting.\n");
abort ();
return SCM_BOOL_F; /* not reached */
tc16_catch_closure = scm_make_smob_type ("catch-closure", 0);
scm_set_smob_apply (tc16_catch_closure, apply_catch_closure, 0, 0, 1);
- scm_c_define ("catch", scm_c_make_gsubr ("catch", 3, 1, 0, pre_init_catch));
- scm_c_define ("throw", scm_c_make_gsubr ("throw", 1, 0, 1, pre_init_throw));
+ catch_var = scm_c_define ("catch", scm_c_make_gsubr ("catch", 3, 1, 0,
+ pre_init_catch));
+ throw_var = scm_c_define ("throw", scm_c_make_gsubr ("throw", 1, 0, 1,
+ pre_init_throw));
#include "libguile/throw.x"
}