summaryrefslogtreecommitdiff
path: root/libguile/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'libguile/init.c')
-rw-r--r--libguile/init.c61
1 files changed, 47 insertions, 14 deletions
diff --git a/libguile/init.c b/libguile/init.c
index 2bcfb76fd..f0743f129 100644
--- a/libguile/init.c
+++ b/libguile/init.c
@@ -261,12 +261,20 @@ typedef int setjmp_type;
typedef long setjmp_type;
#endif
-static void scm_boot_guile_1 SCM_P ((SCM_STACKITEM *base,
- int argc, char **argv,
- void (*main_func) (void *closure,
- int argc,
- char **argv),
- void *closure));
+/* All the data needed to invoke the main function. */
+struct main_func_closure
+{
+ /* the function to call */
+ void (*main_func) SCM_P ((void *closure, int argc, char **argv));
+ void *closure; /* dummy data to pass it */
+ int argc;
+ char **argv; /* the argument list it should receive */
+};
+
+
+static void scm_boot_guile_1 SCM_P ((SCM_STACKITEM *base,
+ struct main_func_closure *closure));
+static SCM invoke_main_func SCM_P ((void *body_data, SCM jmpbuf));
/* Fire up the Guile Scheme interpreter.
@@ -282,6 +290,12 @@ static void scm_boot_guile_1 SCM_P ((SCM_STACKITEM *base,
call scm_set_program_arguments with the final list, so Scheme code
will know which arguments have been processed.
+ scm_boot_guile establishes a catch-all catch handler which prints
+ an error message and exits the process. This means that Guile
+ exits in a coherent way when system errors occur and the user isn't
+ prepared to handle it. If the user doesn't like this behavior,
+ they can establish their own universal catcher to shadow this one.
+
Why must the caller do all the real work from MAIN_FUNC? The
garbage collector assumes that all local variables of type SCM will
be above scm_boot_guile's stack frame on the stack. If you try to
@@ -302,10 +316,17 @@ scm_boot_guile (argc, argv, main_func, closure)
end of the stack, and the address of one of its own local
variables as the other end. */
SCM_STACKITEM dummy;
+ struct main_func_closure c;
- return scm_boot_guile_1 (&dummy, argc, argv, main_func, closure);
+ c.main_func = main_func;
+ c.closure = closure;
+ c.argc = argc;
+ c.argv = argv;
+
+ return scm_boot_guile_1 (&dummy, &c);
}
+
/* Record here whether SCM_BOOT_GUILE_1 has already been called. This
variable is now here and not inside SCM_BOOT_GUILE_1 so that one
can tweak it. This is necessary for unexec to work. (Hey, "1-live"
@@ -314,12 +335,9 @@ scm_boot_guile (argc, argv, main_func, closure)
int scm_boot_guile_1_live = 0;
static void
-scm_boot_guile_1 (base, argc, argv, main_func, closure)
+scm_boot_guile_1 (base, closure)
SCM_STACKITEM *base;
- int argc;
- char **argv;
- void (*main_func) ();
- void *closure;
+ struct main_func_closure *closure;
{
static int initialized = 0;
/* static int live = 0; */
@@ -436,8 +454,9 @@ scm_boot_guile_1 (base, argc, argv, main_func, closure)
{
scm_init_signals ();
- scm_set_program_arguments (argc, argv, 0);
- (*main_func) (closure, argc, argv);
+ scm_set_program_arguments (closure->argc, closure->argv, 0);
+ scm_internal_catch (SCM_BOOL_T, invoke_main_func, closure,
+ scm_handle_by_message, 0);
}
scm_restore_signals ();
@@ -452,3 +471,17 @@ scm_boot_guile_1 (base, argc, argv, main_func, closure)
main_func themselves. */
exit (0);
}
+
+
+static SCM
+invoke_main_func (body_data, jmpbuf)
+ void *body_data;
+ SCM jmpbuf;
+{
+ struct main_func_closure *closure = (struct main_func_closure *) body_data;
+
+ (*closure->main_func) (closure->closure, closure->argc, closure->argv);
+
+ /* never reached */
+ return SCM_UNDEFINED;
+}