SCM_VALIDATE_SMOB uses SCM_SMOB_PREDICATE
[bpt/guile.git] / libguile / throw.c
CommitLineData
5c8cefe5 1/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2003, 2004, 2006, 2008, 2009 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
JB
24
25#include <stdio.h>
27646f41 26#include <unistdio.h>
a0599745 27#include "libguile/_scm.h"
54f2445b 28#include "libguile/async.h"
a0599745
MD
29#include "libguile/smob.h"
30#include "libguile/alist.h"
31#include "libguile/eval.h"
32#include "libguile/eq.h"
33#include "libguile/dynwind.h"
34#include "libguile/backtrace.h"
a0599745 35#include "libguile/debug.h"
a0599745
MD
36#include "libguile/continuations.h"
37#include "libguile/stackchk.h"
38#include "libguile/stacks.h"
39#include "libguile/fluids.h"
40#include "libguile/ports.h"
c96d76b8 41#include "libguile/lang.h"
a0599745
MD
42#include "libguile/validate.h"
43#include "libguile/throw.h"
9de87eea 44#include "libguile/init.h"
a2c40dc7 45#include "libguile/strings.h"
747a1635 46#include "libguile/vm.h"
0f2d19dd 47
22fc179a
HWN
48#include "libguile/private-options.h"
49
50
32f7b3a1 51\f
74229f75 52/* the jump buffer data structure */
92c2555f 53static scm_t_bits tc16_jmpbuffer;
0f2d19dd 54
e841c3e0 55#define SCM_JMPBUFP(OBJ) SCM_TYP16_PREDICATE (tc16_jmpbuffer, OBJ)
c209c88e 56
e841c3e0 57#define JBACTIVE(OBJ) (SCM_CELL_WORD_0 (OBJ) & (1L << 16L))
22a52da1
DH
58#define ACTIVATEJB(x) \
59 (SCM_SET_CELL_WORD_0 ((x), (SCM_CELL_WORD_0 (x) | (1L << 16L))))
60#define DEACTIVATEJB(x) \
61 (SCM_SET_CELL_WORD_0 ((x), (SCM_CELL_WORD_0 (x) & ~(1L << 16L))))
0f2d19dd 62
a4dbe1ac 63#define JBJMPBUF(OBJ) ((scm_i_jmp_buf *) SCM_CELL_WORD_1 (OBJ))
770e048f 64#define SETJBJMPBUF(x, v) (SCM_SET_CELL_WORD_1 ((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 82 SCM_NEWSMOB2 (answer, tc16_jmpbuffer, 0, 0);
a4dbe1ac 83 SETJBJMPBUF(answer, (scm_i_jmp_buf *)0);
86a597f8 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{
a4dbe1ac 93 scm_i_jmp_buf buf; /* must be first */
0f2d19dd
JB
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 177 vm = scm_the_vm ();
5c8cefe5 178 if (scm_is_true (vm))
747a1635
AW
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);
43e01b1e
NJ
188
189 pre_unwind.handler = pre_unwind_handler;
190 pre_unwind.handler_data = pre_unwind_handler_data;
191 pre_unwind.running = 0;
192 pre_unwind.lazy_catch_p = 0;
193 SCM_SETJBPREUNWIND(jmpbuf, &pre_unwind);
194
a4dbe1ac 195 if (SCM_I_SETJMP (jbr.buf))
0f2d19dd
JB
196 {
197 SCM throw_tag;
198 SCM throw_args;
199
7f759d79
MD
200#ifdef STACK_CHECKING
201 scm_stack_checking_enabled_p = SCM_STACK_CHECKING_P;
202#endif
9de87eea 203 SCM_CRITICAL_SECTION_START;
0f2d19dd 204 DEACTIVATEJB (jmpbuf);
9de87eea
MV
205 scm_i_set_dynwinds (SCM_CDR (scm_i_dynwinds ()));
206 SCM_CRITICAL_SECTION_END;
0f2d19dd
JB
207 throw_args = jbr.retval;
208 throw_tag = jbr.throw_tag;
209 jbr.throw_tag = SCM_EOL;
210 jbr.retval = SCM_EOL;
8b22ed7a 211 if (scm_is_true (vm))
747a1635
AW
212 {
213 SCM_VM_DATA (vm)->sp = sp;
214 SCM_VM_DATA (vm)->fp = fp;
215#ifdef VM_ENABLE_STACK_NULLING
216 /* see vm.c -- you'll have to enable this manually */
217 memset (sp + 1, 0,
218 (SCM_VM_DATA (vm)->stack_size
219 - (sp + 1 - SCM_VM_DATA (vm)->stack_base)) * sizeof(SCM));
220#endif
221 }
8b22ed7a 222 else if (scm_is_true ((vm = scm_the_vm ())))
747a1635
AW
223 {
224 /* oof, it's possible this catch was called before the vm was
225 booted... yick. anyway, try to reset the vm stack. */
226 SCM_VM_DATA (vm)->sp = SCM_VM_DATA (vm)->stack_base - 1;
227 SCM_VM_DATA (vm)->fp = NULL;
228#ifdef VM_ENABLE_STACK_NULLING
229 /* see vm.c -- you'll have to enable this manually */
230 memset (SCM_VM_DATA (vm)->stack_base, 0,
231 SCM_VM_DATA (vm)->stack_size * sizeof(SCM));
232#endif
233 }
234
816a6f06 235 answer = handler (handler_data, throw_tag, throw_args);
0f2d19dd
JB
236 }
237 else
238 {
239 ACTIVATEJB (jmpbuf);
492960a4 240 answer = body (body_data);
9de87eea 241 SCM_CRITICAL_SECTION_START;
0f2d19dd 242 DEACTIVATEJB (jmpbuf);
9de87eea
MV
243 scm_i_set_dynwinds (SCM_CDR (scm_i_dynwinds ()));
244 SCM_CRITICAL_SECTION_END;
0f2d19dd
JB
245 }
246 return answer;
247}
248
43e01b1e
NJ
249SCM
250scm_internal_catch (SCM tag,
251 scm_t_catch_body body, void *body_data,
252 scm_t_catch_handler handler, void *handler_data)
253{
254 return scm_c_catch(tag,
255 body, body_data,
256 handler, handler_data,
257 NULL, NULL);
258}
650fa1ab 259
18eadcbe 260
43e01b1e
NJ
261\f
262/* The smob tag for pre_unwind_data smobs. */
263static scm_t_bits tc16_pre_unwind_data;
18eadcbe
JB
264
265/* Strictly speaking, we could just pass a zero for our print
266 function, because we don't need to print them. They should never
267 appear in normal data structures, only in the wind list. However,
268 it might be nice for debugging someday... */
269static int
43e01b1e 270pre_unwind_data_print (SCM closure, SCM port, scm_print_state *pstate SCM_UNUSED)
18eadcbe 271{
43e01b1e 272 struct pre_unwind_data *c = (struct pre_unwind_data *) SCM_CELL_WORD_1 (closure);
18eadcbe
JB
273 char buf[200];
274
43e01b1e 275 sprintf (buf, "#<pre-unwind-data 0x%lx 0x%lx>",
18eadcbe 276 (long) c->handler, (long) c->handler_data);
b7f3516f 277 scm_puts (buf, port);
18eadcbe
JB
278
279 return 1;
280}
281
18eadcbe 282
43e01b1e 283/* Given a pointer to a pre_unwind_data structure, return a smob for it,
18eadcbe
JB
284