Include <config.h> in standalone tests.
[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"
0f2d19dd 44
22fc179a
HWN
45#include "libguile/private-options.h"
46
47
32f7b3a1 48\f
74229f75 49/* the jump buffer data structure */
92c2555f 50static scm_t_bits tc16_jmpbuffer;
0f2d19dd 51
e841c3e0 52#define SCM_JMPBUFP(OBJ) SCM_TYP16_PREDICATE (tc16_jmpbuffer, OBJ)
c209c88e 53
e841c3e0 54#define JBACTIVE(OBJ) (SCM_CELL_WORD_0 (OBJ) & (1L << 16L))
22a52da1
DH
55#define ACTIVATEJB(x) \
56 (SCM_SET_CELL_WORD_0 ((x), (SCM_CELL_WORD_0 (x) | (1L << 16L))))
57#define DEACTIVATEJB(x) \
58 (SCM_SET_CELL_WORD_0 ((x), (SCM_CELL_WORD_0 (x) & ~(1L << 16L))))
0f2d19dd 59
4260a7fc 60#define JBJMPBUF(OBJ) ((jmp_buf *) SCM_CELL_WORD_1 (OBJ))
770e048f 61#define SETJBJMPBUF(x, v) (SCM_SET_CELL_WORD_1 ((x), (scm_t_bits) (v)))
92c2555f 62#define SCM_JBDFRAME(x) ((scm_t_debug_frame *) SCM_CELL_WORD_2 (x))
770e048f 63#define SCM_SETJBDFRAME(x, v) (SCM_SET_CELL_WORD_2 ((x), (scm_t_bits) (v)))
43e01b1e
NJ
64#define SCM_JBPREUNWIND(x) ((struct pre_unwind_data *) SCM_CELL_WORD_3 (x))
65#define SCM_SETJBPREUNWIND(x, v) (SCM_SET_CELL_WORD_3 ((x), (scm_t_bits) (v)))
0f2d19dd 66
0f2d19dd 67static int
e81d98ec 68jmpbuffer_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
0f2d19dd 69{
b7f3516f
TT
70 scm_puts ("#<jmpbuffer ", port);
71 scm_puts (JBACTIVE(exp) ? "(active) " : "(inactive) ", port);
0345e278 72 scm_uintprint((scm_t_bits) JBJMPBUF (exp), 16, port);
b7f3516f 73 scm_putc ('>', port);
0f2d19dd
JB
74 return 1 ;
75}
76
0f2d19dd 77static SCM
1bbd0b84 78make_jmpbuf (void)
0f2d19dd
JB
79{
80 SCM answer;
86a597f8
NJ
81 SCM_NEWSMOB2 (answer, tc16_jmpbuffer, 0, 0);
82 SETJBJMPBUF(answer, (jmp_buf *)0);
83 DEACTIVATEJB(answer);
0f2d19dd
JB
84 return answer;
85}
86
74229f75 87\f
43e01b1e 88/* scm_c_catch (the guts of catch) */
74229f75 89
0f2d19dd
JB
90struct jmp_buf_and_retval /* use only on the stack, in scm_catch */
91{
92 jmp_buf buf; /* must be first */
93 SCM throw_tag;
94 SCM retval;
95};
96
43e01b1e
NJ
97/* These are the structures we use to store pre-unwind handling (aka
98 "lazy") information for a regular catch, and put on the wind list
99 for a "lazy" catch. They store the pre-unwind handler function to
100 call, and the data pointer to pass through to it. It's not a
101 Scheme closure, but it is a function with data, so the term
102 "closure" is appropriate in its broader sense.
650fa1ab 103
43e01b1e
NJ
104 (We don't need anything like this to run the normal (post-unwind)
105 catch handler, because the same C frame runs both the body and the
106 handler.) */
107
108struct pre_unwind_data {
109 scm_t_catch_handler handler;
110 void *handler_data;
111 int running;
112 int lazy_catch_p;
113};
114
115
116/* scm_c_catch is the guts of catch. It handles all the mechanics of
117 setting up a catch target, invoking the catch body, and perhaps
118 invoking the handler if the body does a throw.
650fa1ab
JB
119
120 The function is designed to be usable from C code, but is general
121 enough to implement all the semantics Guile Scheme expects from
122 throw.
123
124 TAG is the catch tag. Typically, this is a symbol, but this
125 function doesn't actually care about that.
126
127 BODY is a pointer to a C function which runs the body of the catch;
128 this is the code you can throw from. We call it like this:
19b27fa2 129 BODY (BODY_DATA)
650fa1ab 130 where:
816a6f06
JB
131 BODY_DATA is just the BODY_DATA argument we received; we pass it
132 through to BODY as its first argument. The caller can make
133 BODY_DATA point to anything useful that BODY might need.
650fa1ab
JB
134
135 HANDLER is a pointer to a C function to deal with a throw to TAG,
136 should one occur. We call it like this:
86327304 137 HANDLER (HANDLER_DATA, THROWN_TAG, THROW_ARGS)
650fa1ab 138 where
816a6f06
JB
139 HANDLER_DATA is the HANDLER_DATA argument we recevied; it's the
140 same idea as BODY_DATA above.
86327304
JB
141 THROWN_TAG is the tag that the user threw to; usually this is
142 TAG, but it could be something else if TAG was #t (i.e., a
143 catch-all), or the user threw to a jmpbuf.
650fa1ab 144 THROW_ARGS is the list of arguments the user passed to the THROW
4dd8323f 145 function, after the tag.
650fa1ab 146
3eed3475
JB
147 BODY_DATA is just a pointer we pass through to BODY. HANDLER_DATA
148 is just a pointer we pass through to HANDLER. We don't actually
149 use either of those pointers otherwise ourselves. The idea is
150 that, if our caller wants to communicate something to BODY or
151 HANDLER, it can pass a pointer to it as MUMBLE_DATA, which BODY and
152 HANDLER can then use. Think of it as a way to make BODY and
153 HANDLER closures, not just functions; MUMBLE_DATA points to the
154 enclosed variables.
155
156 Of course, it's up to the caller to make sure that any data a
157 MUMBLE_DATA needs is protected from GC. A common way to do this is
158 to make MUMBLE_DATA a pointer to data stored in an automatic
159 structure variable; since the collector must scan the stack for
160 references anyway, this assures that any references in MUMBLE_DATA
161 will be found. */
650fa1ab 162
0f2d19dd 163SCM
43e01b1e
NJ
164scm_c_catch (SCM tag,
165 scm_t_catch_body body, void *body_data,
166 scm_t_catch_handler handler, void *handler_data,
167 scm_t_catch_handler pre_unwind_handler, void *pre_unwind_handler_data)
0f2d19dd
JB
168{
169 struct jmp_buf_and_retval jbr;
170 SCM jmpbuf;
171 SCM answer;
43e01b1e 172 struct pre_unwind_data pre_unwind;
0f2d19dd 173
11702758 174 jmpbuf = make_jmpbuf ();
0f2d19dd 175 answer = SCM_EOL;
9de87eea 176 scm_i_set_dynwinds (scm_acons (tag, jmpbuf, scm_i_dynwinds ()));
0f2d19dd 177 SETJBJMPBUF(jmpbuf, &jbr.buf);
9de87eea 178 SCM_SETJBDFRAME(jmpbuf, scm_i_last_debug_frame ());
43e01b1e
NJ
179
180 pre_unwind.handler = pre_unwind_handler;
181 pre_unwind.handler_data = pre_unwind_handler_data;
182 pre_unwind.running = 0;
183 pre_unwind.lazy_catch_p = 0;
184 SCM_SETJBPREUNWIND(jmpbuf, &pre_unwind);
185
0f2d19dd
JB
186 if (setjmp (jbr.buf))
187 {
188 SCM throw_tag;
189 SCM throw_args;
190
7f759d79
MD
191#ifdef STACK_CHECKING
192 scm_stack_checking_enabled_p = SCM_STACK_CHECKING_P;
193#endif
9de87eea 194 SCM_CRITICAL_SECTION_START;
0f2d19dd 195 DEACTIVATEJB (jmpbuf);
9de87eea
MV
196 scm_i_set_dynwinds (SCM_CDR (scm_i_dynwinds ()));
197 SCM_CRITICAL_SECTION_END;
0f2d19dd
JB
198 throw_args = jbr.retval;
199 throw_tag = jbr.throw_tag;
200 jbr.throw_tag = SCM_EOL;
201 jbr.retval = SCM_EOL;
816a6f06 202 answer = handler (handler_data, throw_tag, throw_args);
0f2d19dd
JB
203 }
204 else
205 {
206 ACTIVATEJB (jmpbuf);
492960a4 207 answer = body (body_data);
9de87eea 208 SCM_CRITICAL_SECTION_START;
0f2d19dd 209 DEACTIVATEJB (jmpbuf);
9de87eea
MV
210 scm_i_set_dynwinds (SCM_CDR (scm_i_dynwinds ()));
211 SCM_CRITICAL_SECTION_END;
0f2d19dd
JB
212 }
213 return answer;
214}
215
43e01b1e
NJ
216SCM
217scm_internal_catch (SCM tag,
218 scm_t_catch_body body, void *body_data,
219 scm_t_catch_handler handler, void *handler_data)
220{
221 return scm_c_catch(tag,
222 body, body_data,
223 handler, handler_data,
224 NULL, NULL);
225}
650fa1ab 226
18eadcbe 227
43e01b1e
NJ
228\f
229/* The smob tag for pre_unwind_data smobs. */
230static scm_t_bits tc16_pre_unwind_data;
18eadcbe
JB
231
232/* Strictly speaking, we could just pass a zero for our print
233 function, because we don't need to print them. They should never
234 appear in normal data structures, only in the wind list. However,
235 it might be nice for debugging someday... */
236static int
43e01b1e 237pre_unwind_data_print (SCM closure, SCM port, scm_print_state *pstate SCM_UNUSED)
18eadcbe 238{
43e01b1e 239 struct pre_unwind_data *c = (struct pre_unwind_data *) SCM_CELL_WORD_1 (closure);
18eadcbe
JB
240 char buf[200];
241
43e01b1e 242 sprintf (buf, "#<pre-unwind-data 0x%lx 0x%lx>",
18eadcbe 243 (long) c->handler, (long) c->handler_data);
b7f3516f 244 scm_puts (buf, port);
18eadcbe
JB
245
246 return 1;
247}
248
18eadcbe 249
43e01b1e 250/* Given a pointer to a pre_unwind_data structure, return a smob for it,
18eadcbe
JB
251