Merge commit 'feccd2d3100fd2964d4c2df58ab3da7ce4949a66' into vm-check
[bpt/guile.git] / libguile / throw.c
CommitLineData
86a597f8 1/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2003, 2004, 2006, 2008 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
0f2d19dd 7 *
73be1d9e
MV
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
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
92205699 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
73be1d9e 16 */
1bbd0b84 17
1bbd0b84 18
0f2d19dd 19\f
dbb605f5
LC
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
0f2d19dd
JB
23
24#include <stdio.h>
a0599745 25#include "libguile/_scm.h"
54f2445b 26#include "libguile/async.h"
a0599745
MD
27#include "libguile/smob.h"
28#include "libguile/alist.h"
29#include "libguile/eval.h"
30#include "libguile/eq.h"
31#include "libguile/dynwind.h"
32#include "libguile/backtrace.h"
a0599745 33#include "libguile/debug.h"
a0599745
MD
34#include "libguile/continuations.h"
35#include "libguile/stackchk.h"
36#include "libguile/stacks.h"
37#include "libguile/fluids.h"
38#include "libguile/ports.h"
c96d76b8 39#include "libguile/lang.h"
a0599745
MD
40#include "libguile/validate.h"
41#include "libguile/throw.h"
9de87eea 42#include "libguile/init.h"
a2c40dc7 43#include "libguile/strings.h"
747a1635 44#include "libguile/vm.h"
0f2d19dd 45
22fc179a
HWN
46#include "libguile/private-options.h"
47
48
32f7b3a1 49\f
74229f75 50/* the jump buffer data structure */
92c2555f 51static scm_t_bits tc16_jmpbuffer;
0f2d19dd 52
e841c3e0 53#define SCM_JMPBUFP(OBJ) SCM_TYP16_PREDICATE (tc16_jmpbuffer, OBJ)
c209c88e 54
e841c3e0 55#define JBACTIVE(OBJ) (SCM_CELL_WORD_0 (OBJ) & (1L << 16L))
22a52da1
DH
56#define ACTIVATEJB(x) \
57 (SCM_SET_CELL_WORD_0 ((x), (SCM_CELL_WORD_0 (x) | (1L << 16L))))
58#define DEACTIVATEJB(x) \
59 (SCM_SET_CELL_WORD_0 ((x), (SCM_CELL_WORD_0 (x) & ~(1L << 16L))))
0f2d19dd 60
4260a7fc 61#define JBJMPBUF(OBJ) ((jmp_buf *) SCM_CELL_WORD_1 (OBJ))
770e048f 62#define SETJBJMPBUF(x, v) (SCM_SET_CELL_WORD_1 ((x), (scm_t_bits) (v)))
92c2555f 63#define SCM_JBDFRAME(x) ((scm_t_debug_frame *) SCM_CELL_WORD_2 (x))
770e048f 64#define SCM_SETJBDFRAME(x, v) (SCM_SET_CELL_WORD_2 ((x), (scm_t_bits) (v)))
43e01b1e
NJ
65#define SCM_JBPREUNWIND(x) ((struct pre_unwind_data *) SCM_CELL_WORD_3 (x))
66#define SCM_SETJBPREUNWIND(x, v) (SCM_SET_CELL_WORD_3 ((x), (scm_t_bits) (v)))
0f2d19dd 67
0f2d19dd 68static int
e81d98ec 69jmpbuffer_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
0f2d19dd 70{
b7f3516f
TT
71 scm_puts ("#<jmpbuffer ", port);
72 scm_puts (JBACTIVE(exp) ? "(active) " : "(inactive) ", port);
0345e278 73 scm_uintprint((scm_t_bits) JBJMPBUF (exp), 16, port);
b7f3516f 74 scm_putc ('>', port);
0f2d19dd
JB
75 return 1 ;
76}
77
0f2d19dd 78static SCM
1bbd0b84 79make_jmpbuf (void)
0f2d19dd
JB
80{
81 SCM answer;
86a597f8
NJ
82 SCM_NEWSMOB2 (answer, tc16_jmpbuffer, 0, 0);
83 SETJBJMPBUF(answer, (jmp_buf *)0);
84 DEACTIVATEJB(answer);
0f2d19dd
JB
85 return answer;
86}
87
74229f75 88\f
43e01b1e 89/* scm_c_catch (the guts of catch) */
74229f75 90
0f2d19dd
JB
91struct jmp_buf_and_retval /* use only on the stack, in scm_catch */
92{
93 jmp_buf buf; /* must be first */
94 SCM throw_tag;
95 SCM retval;
96};
97
43e01b1e
NJ
98/* These are the structures we use to store pre-unwind handling (aka
99 "lazy") information for a regular catch, and put on the wind list
100 for a "lazy" catch. They store the pre-unwind handler function to
101 call, and the data pointer to pass through to it. It's not a
102 Scheme closure, but it is a function with data, so the term
103 "closure" is appropriate in its broader sense.
650fa1ab 104
43e01b1e
NJ
105 (We don't need anything like this to run the normal (post-unwind)
106 catch handler, because the same C frame runs both the body and the
107 handler.) */
108
109struct pre_unwind_data {
110 scm_t_catch_handler handler;
111 void *handler_data;
112 int running;
113 int lazy_catch_p;
114};
115
116
117/* scm_c_catch is the guts of catch. It handles all the mechanics of
118 setting up a catch target, invoking the catch body, and perhaps
119 invoking the handler if the body does a throw.
650fa1ab
JB
120
121 The function is designed to be usable from C code, but is general
122 enough to implement all the semantics Guile Scheme expects from
123 throw.
124
125 TAG is the catch tag. Typically, this is a symbol, but this
126 function doesn't actually care about that.
127
128 BODY is a pointer to a C function which runs the body of the catch;
129 this is the code you can throw from. We call it like this:
19b27fa2 130 BODY (BODY_DATA)
650fa1ab 131 where:
816a6f06
JB
132 BODY_DATA is just the BODY_DATA argument we received; we pass it
133 through to BODY as its first argument. The caller can make
134 BODY_DATA point to anything useful that BODY might need.
650fa1ab
JB
135
136 HANDLER is a pointer to a C function to deal with a throw to TAG,
137 should one occur. We call it like this:
86327304 138 HANDLER (HANDLER_DATA, THROWN_TAG, THROW_ARGS)
650fa1ab 139 where
816a6f06
JB
140 HANDLER_DATA is the HANDLER_DATA argument we recevied; it's the
141 same idea as BODY_DATA above.
86327304
JB
142 THROWN_TAG is the tag that the user threw to; usually this is
143 TAG, but it could be something else if TAG was #t (i.e., a
144 catch-all), or the user threw to a jmpbuf.
650fa1ab 145 THROW_ARGS is the list of arguments the user passed to the THROW
4dd8323f 146 function, after the tag.
650fa1ab 147
3eed3475
JB
148 BODY_DATA is just a pointer we pass through to BODY. HANDLER_DATA
149 is just a pointer we pass through to HANDLER. We don't actually
150 use either of those pointers otherwise ourselves. The idea is
151 that, if our caller wants to communicate something to BODY or
152 HANDLER, it can pass a pointer to it as MUMBLE_DATA, which BODY and
153 HANDLER can then use. Think of it as a way to make BODY and
154 HANDLER closures, not just functions; MUMBLE_DATA points to the
155 enclosed variables.
156
157 Of course, it's up to the caller to make sure that any data a
158 MUMBLE_DATA needs is protected from GC. A common way to do this is
159 to make MUMBLE_DATA a pointer to data stored in an automatic
160 structure variable; since the collector must scan the stack for
161 references anyway, this assures that any references in MUMBLE_DATA
162 will be found. */
650fa1ab 163
0f2d19dd 164SCM
43e01b1e
NJ
165scm_c_catch (SCM tag,
166 scm_t_catch_body body, void *body_data,
167 scm_t_catch_handler handler, void *handler_data,
168 scm_t_catch_handler pre_unwind_handler, void *pre_unwind_handler_data)
0f2d19dd
JB
169{
170 struct jmp_buf_and_retval jbr;
171 SCM jmpbuf;
172 SCM answer;
747a1635
AW
173 SCM vm;
174 SCM *sp = NULL, *fp = NULL; /* to reset the vm */
43e01b1e 175 struct pre_unwind_data pre_unwind;
0f2d19dd 176
747a1635
AW
177 vm = scm_the_vm ();
178 if (SCM_NFALSEP (vm))
179 {
180 sp = SCM_VM_DATA (vm)->sp;
181 fp = SCM_VM_DATA (vm)->fp;
182 }
183
11702758 184 jmpbuf = make_jmpbuf ();
0f2d19dd 185 answer = SCM_EOL;
9de87eea 186 scm_i_set_dynwinds (scm_acons (tag, jmpbuf, scm_i_dynwinds ()));
0f2d19dd 187 SETJBJMPBUF(jmpbuf, &jbr.buf);
9de87eea 188 SCM_SETJBDFRAME(jmpbuf, scm_i_last_debug_frame ());
43e01b1e
NJ
189
190 pre_unwind.handler = pre_unwind_handler;
191 pre_unwind.handler_data = pre_unwind_handler_data;
192 pre_unwind.running = 0;
193 pre_unwind.lazy_catch_p = 0;
194 SCM_SETJBPREUNWIND(jmpbuf, &pre_unwind);
195
0f2d19dd
JB
196 if (setjmp (jbr.buf))
197 {
198 SCM throw_tag;
199 SCM throw_args;
200
7f759d79
MD
201#ifdef STACK_CHECKING
202 scm_stack_checking_enabled_p = SCM_STACK_CHECKING_P;
203#endif
9de87eea 204 SCM_CRITICAL_SECTION_START;
0f2d19dd 205 DEACTIVATEJB (jmpbuf);
9de87eea
MV
206 scm_i_set_dynwinds (SCM_CDR (scm_i_dynwinds ()));
207 SCM_CRITICAL_SECTION_END;
0f2d19dd
JB
208 throw_args = jbr.retval;
209 throw_tag = jbr.throw_tag;
210 jbr.throw_tag = SCM_EOL;
211 jbr.retval = SCM_EOL;
747a1635
AW
212 if (SCM_NFALSEP (vm))
213 {
214 SCM_VM_DATA (vm)->sp = sp;
215 SCM_VM_DATA (vm)->fp = fp;
216#ifdef VM_ENABLE_STACK_NULLING
217 /* see vm.c -- you'll have to enable this manually */
218 memset (sp + 1, 0,
219 (SCM_VM_DATA (vm)->stack_size
220 - (sp + 1 - SCM_VM_DATA (vm)->stack_base)) * sizeof(SCM));
221#endif
222 }
223 else if (SCM_NFALSEP ((vm = scm_the_vm ())))
224 {
225 /* oof, it's possible this catch was called before the vm was
226 booted... yick. anyway, try to reset the vm stack. */
227 SCM_VM_DATA (vm)->sp = SCM_VM_DATA (vm)->stack_base - 1;
228 SCM_VM_DATA (vm)->fp = NULL;
229#ifdef VM_ENABLE_STACK_NULLING
230 /* see vm.c -- you'll have to enable this manually */
231 memset (SCM_VM_DATA (vm)->stack_base, 0,
232 SCM_VM_DATA (vm)->stack_size * sizeof(SCM));
233#endif
234 }
235
816a6f06 236 answer = handler (handler_data, throw_tag, throw_args);
0f2d19dd
JB
237 }
238 else
239 {
240 ACTIVATEJB (jmpbuf);
492960a4 241 answer = body (body_data);
9de87eea 242 SCM_CRITICAL_SECTION_START;
0f2d19dd 243 DEACTIVATEJB (jmpbuf);
9de87eea
MV
244 scm_i_set_dynwinds (SCM_CDR (scm_i_dynwinds ()));
245 SCM_CRITICAL_SECTION_END;
0f2d19dd
JB
246 }
247 return answer;
248}
249
43e01b1e
NJ
250SCM
251scm_internal_catch (SCM tag,
252 scm_t_catch_body body, void *body_data,
253 scm_t_catch_handler handler, void *handler_data)
254{
255 return scm_c_catch(tag,
256 body, body_data,
257 handler, handler_data,
258 NULL, NULL);
259}
650fa1ab 260
18eadcbe 261
43e01b1e
NJ
262\f
263/* The smob tag for pre_unwind_data smobs. */
264static scm_t_bits tc16_pre_unwind_data;
18eadcbe
JB
265
266/* Strictly speaking, we could just pass a zero for our print
267 function, because we don't need to print them. They should never
268 appear in normal data structures, only in the wind list. However,
269 it might be nice for debugging someday... */
270static int
43e01b1e 271pre_unwind_data_print (SCM closure, SCM port, scm_print_state *pstate SCM_UNUSED)
18eadcbe 272{
43e01b1e 273 struct pre_unwind_data *c = (struct pre_unwind_data *) SCM_CELL_WORD_1 (closure);
18eadcbe
JB
274 char buf[200];
275
43e01b1e 276 sprintf (buf, "#<pre-unwind-data 0x%lx 0x%lx>",
18eadcbe 277 (long) c->handler, (long) c->handler_data);
b7f3516f 278 scm_puts (buf, port);
18eadcbe
JB
279
280 return 1;
281}
282
18eadcbe 283
43e01b1e 284/* Given a pointer to a pre_unwind_data structure, return a smob for it,
18eadcbe
JB
285