further boot cleanups
[bpt/guile.git] / libguile / root.c
CommitLineData
dbb605f5 1/* Copyright (C) 1995,1996,1997,1998,1999,2000, 2001, 2002, 2006, 2008 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
0f2d19dd 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
0f2d19dd 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
73be1d9e 17 */
1bbd0b84 18
1bbd0b84 19
0f2d19dd 20\f
dbb605f5
LC
21#ifdef HAVE_CONFIG_H
22# include <config.h>
23#endif
0f2d19dd 24
783e7774 25#include <string.h>
9de87eea
MV
26#include <stdio.h>
27
a0599745
MD
28#include "libguile/_scm.h"
29#include "libguile/stackchk.h"
30#include "libguile/dynwind.h"
31#include "libguile/eval.h"
32#include "libguile/smob.h"
33#include "libguile/pairs.h"
34#include "libguile/throw.h"
35#include "libguile/fluids.h"
36#include "libguile/ports.h"
37
38#include "libguile/root.h"
0f2d19dd
JB
39\f
40
41SCM scm_sys_protects[SCM_NUM_PROTECTS];
d564d753 42
d564d753
MD
43\f
44
1cc91f1b 45/* {call-with-dynamic-root}
d564d753
MD
46 *
47 * Suspending the current thread to evaluate a thunk on the
48 * same C stack but under a new root.
49 *
1cc91f1b 50 * Calls to call-with-dynamic-root return exactly once (unless
e71575d9 51 * the process is somehow exitted). */
d564d753 52
e71575d9
MV
53/* cwdr fills out both of these structures, and then passes a pointer
54 to them through scm_internal_catch to the cwdr_body and
55 cwdr_handler functions, to tell them how to behave and to get
56 information back from them.
650fa1ab
JB
57
58 A cwdr is a lot like a catch, except there is no tag (all
59 exceptions are caught), and the body procedure takes the arguments
e71575d9
MV
60 passed to cwdr as A1 and ARGS. The handler is also special since
61 it is not directly run from scm_internal_catch. It is executed
62 outside the new dynamic root. */
650fa1ab
JB
63
64struct cwdr_body_data {
650fa1ab
JB
65 /* Arguments to pass to the cwdr body function. */
66 SCM a1, args;
67
68 /* Scheme procedure to use as body of cwdr. */
69 SCM body_proc;
e71575d9
MV
70};
71
72struct cwdr_handler_data {
73 /* Do we need to run the handler? */
74 int run_handler;
f032b8a8 75
e71575d9
MV
76 /* The tag and args to pass it. */
77 SCM tag, args;
650fa1ab
JB
78};
79
80
81/* Invoke the body of a cwdr, assuming that the throw handler has
82 already been set up. DATA points to a struct set up by cwdr that
816a6f06
JB
83 says what proc to call, and what args to apply it to.
84
85 With a little thought, we could replace this with scm_body_thunk,
86 but I don't want to mess with that at the moment. */
650fa1ab 87static SCM
39752bec 88cwdr_body (void *data)
650fa1ab
JB
89{
90 struct cwdr_body_data *c = (struct cwdr_body_data *) data;
91
92 return scm_apply (c->body_proc, c->a1, c->args);
93}
94
e71575d9
MV
95/* Record the fact that the body of the cwdr has thrown. Record
96 enough information to invoke the handler later when the dynamic
97 root has been deestablished. */
650fa1ab 98
f032b8a8 99static SCM
e71575d9 100cwdr_handler (void *data, SCM tag, SCM args)
f032b8a8 101{
e71575d9 102 struct cwdr_handler_data *c = (struct cwdr_handler_data *) data;
f032b8a8 103
e71575d9
MV
104 c->run_handler = 1;
105 c->tag = tag;
106 c->args = args;
107 return SCM_UNSPECIFIED;
f032b8a8 108}
d564d753 109
e71575d9 110SCM
92c2555f
MV
111scm_internal_cwdr (scm_t_catch_body body, void *body_data,
112 scm_t_catch_handler handler, void *handler_data,
e71575d9 113 SCM_STACKITEM *stack_start)
d564d753 114{
e71575d9 115 struct cwdr_handler_data my_handler_data;
9de87eea 116 SCM answer, old_winds;
d564d753 117
8938d022
MD
118 /* Exit caller's dynamic state.
119 */
9de87eea
MV
120 old_winds = scm_i_dynwinds ();
121 scm_dowinds (SCM_EOL, scm_ilength (old_winds));
122
661ae7ab
MV
123 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
124 scm_dynwind_current_dynamic_state (scm_make_dynamic_state (SCM_UNDEFINED));
e71575d9 125
9de87eea
MV
126 my_handler_data.run_handler = 0;
127 answer = scm_i_with_continuation_barrier (body, body_data,
43e01b1e
NJ
128 cwdr_handler, &my_handler_data,
129 NULL, NULL);
9de87eea 130
661ae7ab 131 scm_dynwind_end ();
9de87eea
MV
132
133 /* Enter caller's dynamic state.
134 */
d564d753 135 scm_dowinds (old_winds, - scm_ilength (old_winds));
e71575d9
MV
136
137 /* Now run the real handler iff the body did a throw. */
138 if (my_handler_data.run_handler)
139 return handler (handler_data, my_handler_data.tag, my_handler_data.args);
140 else
141 return answer;
d564d753
MD
142}
143
e71575d9
MV
144/* The original CWDR for invoking Scheme code with a Scheme handler. */
145
146static SCM
147cwdr (SCM proc, SCM a1, SCM args, SCM handler, SCM_STACKITEM *stack_start)
148{
149 struct cwdr_body_data c;
150
151 c.a1 = a1;
152 c.args = args;
153 c.body_proc = proc;
154
155 return scm_internal_cwdr (cwdr_body, &c,
156 scm_handle_by_proc, &handler,
157 stack_start);
158}
d564d753 159
3b3b36dd 160SCM_DEFINE (scm_call_with_dynamic_root, "call-with-dynamic-root", 2, 0, 0,
1bbd0b84 161 (SCM thunk, SCM handler),
9eaf7f85
MV
162 "Call @var{thunk} with a new dynamic state and within"
163 "a continuation barrier. The @var{handler} catches all"
164 "otherwise uncaught throws and executes within the same"
165 "dynamic context as @var{thunk}.")
1bbd0b84 166#define FUNC_NAME s_scm_call_with_dynamic_root
d564d753
MD
167{
168 SCM_STACKITEM stack_place;
8938d022 169 return cwdr (thunk, SCM_EOL, SCM_EOL, handler, &stack_place);
d564d753 170}
1bbd0b84 171#undef FUNC_NAME
d564d753 172
3b3b36dd 173SCM_DEFINE (scm_dynamic_root, "dynamic-root", 0, 0, 0,
1bbd0b84 174 (),
b380b885 175 "Return an object representing the current dynamic root.\n\n"
9de87eea 176 "These objects are only useful for comparison using @code{eq?}.\n")
1bbd0b84 177#define FUNC_NAME s_scm_dynamic_root
d564d753 178{
9de87eea 179 return SCM_I_CURRENT_THREAD->continuation_root;
d564d753 180}
1bbd0b84 181#undef FUNC_NAME
d564d753 182
d564d753 183SCM
1bbd0b84 184scm_apply_with_dynamic_root (SCM proc, SCM a1, SCM args, SCM handler)
d564d753
MD
185{
186 SCM_STACKITEM stack_place;
8938d022 187 return cwdr (proc, a1, args, handler, &stack_place);
d564d753 188}
0f2d19dd
JB
189
190\f
191
d564d753
MD
192void
193scm_init_root ()
194{
a0599745 195#include "libguile/root.x"
d564d753 196}
89e00824
ML
197
198/*
199 Local Variables:
200 c-file-style: "gnu"
201 End:
202*/