Unwind-only stack overflow exceptions
[bpt/guile.git] / libguile / throw.c
CommitLineData
5d20fd49 1/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2003, 2004, 2006, 2008, 2009, 2010, 2011, 2012, 2013, 2014 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
MD
27#include "libguile/_scm.h"
28#include "libguile/smob.h"
a0599745
MD
29#include "libguile/eval.h"
30#include "libguile/eq.h"
416f26c7 31#include "libguile/control.h"
e10cf6b9 32#include "libguile/deprecation.h"
a0599745 33#include "libguile/backtrace.h"
a0599745 34#include "libguile/debug.h"
a0599745
MD
35#include "libguile/stackchk.h"
36#include "libguile/stacks.h"
37#include "libguile/fluids.h"
38#include "libguile/ports.h"
a0599745 39#include "libguile/validate.h"
416f26c7 40#include "libguile/vm.h"
a0599745 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
7e2fd4e7
AW
48/* Pleasantly enough, the guts of catch are defined in Scheme, in terms
49 of prompt, abort, and the %exception-handler fluid. Check boot-9 for
50 the definitions.
51
52 Still, it's useful to be able to throw unwind-only exceptions from C,
53 for example so that we can recover from stack overflow. We also need
54 to have an implementation of catch and throw handy before boot time.
55 For that reason we have a parallel implementation of "catch" that
56 uses the same fluids here. Throws from C still call out to Scheme
57 though, so that pre-unwind handlers can be run. Getting the dynamic
58 environment right for pre-unwind handlers is tricky, and it's
59 important to have all of the implementation in one place.
0f2d19dd 60
416f26c7
AW
61 All of these function names and prototypes carry a fair bit of historical
62 baggage. */
c209c88e 63
0f2d19dd 64
416f26c7
AW
65\f
66
7e2fd4e7 67static SCM throw_var;
60617d81 68
5d20fd49
AW
69static SCM exception_handler_fluid;
70
7e2fd4e7
AW
71static SCM
72catch (SCM tag, SCM thunk, SCM handler, SCM pre_unwind_handler)
73{
74 struct scm_vm *vp;
75 SCM eh, prompt_tag;
76 SCM res;
77 scm_t_dynstack *dynstack = &SCM_I_CURRENT_THREAD->dynstack;
78 SCM dynamic_state = SCM_I_CURRENT_THREAD->dynamic_state;
79 scm_i_jmp_buf registers;
80 scm_t_ptrdiff saved_stack_depth;
81
82 if (!scm_is_eq (tag, SCM_BOOL_T) && !scm_is_symbol (tag))
83 scm_wrong_type_arg ("catch", 1, tag);
84
85 if (SCM_UNBNDP (handler))
86 handler = SCM_BOOL_F;
87 else if (!scm_is_true (scm_procedure_p (handler)))
88 scm_wrong_type_arg ("catch", 3, handler);
89
90 if (SCM_UNBNDP (pre_unwind_handler))
91 pre_unwind_handler = SCM_BOOL_F;
92 else if (!scm_is_true (scm_procedure_p (pre_unwind_handler)))
93 scm_wrong_type_arg ("catch", 4, pre_unwind_handler);
94
95 prompt_tag = scm_cons (SCM_INUM0, SCM_EOL);
96
97 eh = scm_c_make_vector (4, SCM_BOOL_F);
98 scm_c_vector_set_x (eh, 0, scm_fluid_ref (exception_handler_fluid));
99 scm_c_vector_set_x (eh, 1, tag);
100 scm_c_vector_set_x (eh, 2, prompt_tag);
101 scm_c_vector_set_x (eh, 3, pre_unwind_handler);
102
103 vp = scm_the_vm ();
104 saved_stack_depth = vp->sp - vp->stack_base;
105
106 /* Push the prompt and exception handler onto the dynamic stack. */
107 scm_dynstack_push_prompt (dynstack,
108 SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY
109 | SCM_F_DYNSTACK_PROMPT_PUSH_NARGS,
110 prompt_tag,
111 vp->fp - vp->stack_base,
112 saved_stack_depth,
113 vp->ip,
114 &registers);
115 scm_dynstack_push_fluid (dynstack, exception_handler_fluid, eh,
116 dynamic_state);
117
118 if (SCM_I_SETJMP (registers))
119 {
120 /* A non-local return. */
121
122 /* FIXME: We know where the args will be on the stack; we could
123 avoid consing them. */
124 SCM args = scm_i_prompt_pop_abort_args_x (vp);
125
126 /* Cdr past the continuation. */
127 args = scm_cdr (args);
128
129 return scm_apply_0 (handler, args);
130 }
131
132 res = scm_call_0 (thunk);
133
134 scm_dynstack_unwind_fluid (dynstack, dynamic_state);
135 scm_dynstack_pop (dynstack);
136
137 return res;
138}
139
140static void
141default_exception_handler (SCM k, SCM args)
142{
143 static int error_printing_error = 0;
144 static int error_printing_fallback = 0;
145
146 if (error_printing_fallback)
147 fprintf (stderr, "\nFailed to print exception.\n");
148 else if (error_printing_error)
149 {
150 fprintf (stderr, "\nError while printing exception:\n");
151 error_printing_fallback = 1;
152 fprintf (stderr, "Key: ");
153 scm_write (k, scm_current_error_port ());
154 fprintf (stderr, ", args: ");
155 scm_write (args, scm_current_error_port ());
156 scm_newline (scm_current_error_port ());
157 }
158 else
159 {
160 fprintf (stderr, "Uncaught exception:\n");
161 error_printing_error = 1;
162 scm_handle_by_message (NULL, k, args);
163 }
164
165 /* Normally we don't get here, because scm_handle_by_message will
166 exit. */
167 fprintf (stderr, "Aborting.\n");
168 abort ();
169}
170
171static SCM
172throw_without_pre_unwind (SCM tag, SCM args)
173{
174 SCM eh;
175
176 for (eh = scm_fluid_ref (exception_handler_fluid);
177 scm_is_true (eh);
178 eh = scm_c_vector_ref (eh, 0))
179 {
180 SCM catch_key, prompt_tag;
181
182 catch_key = scm_c_vector_ref (eh, 1);
183 if (!scm_is_eq (catch_key, SCM_BOOL_T) && !scm_is_eq (catch_key, tag))
184 continue;
185
186 if (scm_is_true (scm_c_vector_ref (eh, 3)))
187 fprintf (stderr, "\nWarning: unwind-only exception, perhaps due to "
188 "stack overflow; not running pre-unwind handlers.");
189
190 prompt_tag = scm_c_vector_ref (eh, 2);
191 if (scm_is_true (prompt_tag))
192 scm_abort_to_prompt_star (prompt_tag, scm_cons (tag, args));
193 }
194
195 default_exception_handler (tag, args);
196 return SCM_UNSPECIFIED;
197}
198
416f26c7
AW
199SCM
200scm_catch (SCM key, SCM thunk, SCM handler)
0f2d19dd 201{
7e2fd4e7 202 return catch (key, thunk, handler, SCM_UNDEFINED);
0f2d19dd
JB
203}
204
416f26c7
AW
205SCM
206scm_catch_with_pre_unwind_handler (SCM key, SCM thunk, SCM handler,
207 SCM pre_unwind_handler)
0f2d19dd 208{
7e2fd4e7 209 return catch (key, thunk, handler, pre_unwind_handler);
0f2d19dd
JB
210}
211
416f26c7
AW
212SCM
213scm_with_throw_handler (SCM key, SCM thunk, SCM handler)
214{
7e2fd4e7 215 return catch (key, thunk, SCM_UNDEFINED, handler);
416f26c7 216}
74229f75 217
416f26c7
AW
218SCM
219scm_throw (SCM key, SCM args)
0f2d19dd 220{
60617d81 221 return scm_apply_1 (scm_variable_ref (throw_var), key, args);
416f26c7
AW
222}
223
224\f
0f2d19dd 225
416f26c7 226/* Now some support for C bodies and catch handlers */
650fa1ab 227
416f26c7 228static scm_t_bits tc16_catch_closure;
43e01b1e 229
416f26c7
AW
230enum {
231 CATCH_CLOSURE_BODY,
232 CATCH_CLOSURE_HANDLER
43e01b1e
NJ
233};
234
416f26c7
AW
235static SCM
236make_catch_body_closure (scm_t_catch_body body, void *body_data)
237{
238 SCM ret;
239 SCM_NEWSMOB2 (ret, tc16_catch_closure, body, body_data);
240 SCM_SET_SMOB_FLAGS (ret, CATCH_CLOSURE_BODY);
241 return ret;
242}
243
244static SCM
245make_catch_handler_closure (scm_t_catch_handler handler, void *handler_data)
246{
247 SCM ret;
248 SCM_NEWSMOB2 (ret, tc16_catch_closure, handler, handler_data);
249 SCM_SET_SMOB_FLAGS (ret, CATCH_CLOSURE_HANDLER);
250 return ret;
251}
43e01b1e 252
416f26c7
AW
253static SCM
254apply_catch_closure (SCM clo, SCM args)
255{
256 void *data = (void*)SCM_SMOB_DATA_2 (clo);
650fa1ab 257
416f26c7
AW
258 switch (SCM_SMOB_FLAGS (clo))
259 {
260 case CATCH_CLOSURE_BODY:
261 {
262 scm_t_catch_body body = (void*)SCM_SMOB_DATA (clo);
263 return body (data);
264 }
265 case CATCH_CLOSURE_HANDLER:
266 {
267 scm_t_catch_handler handler = (void*)SCM_SMOB_DATA (clo);
268 return handler (data, scm_car (args), scm_cdr (args));
269 }
270 default:
271 abort ();
272 }
273}
650fa1ab 274
416f26c7 275/* TAG is the catch tag. Typically, this is a symbol, but this
650fa1ab
JB
276 function doesn't actually care about that.
277
278 BODY is a pointer to a C function which runs the body of the catch;
279 this is the code you can throw from. We call it like this:
19b27fa2 280 BODY (BODY_DATA)
650fa1ab 281 where:
816a6f06
JB
282 BODY_DATA is just the BODY_DATA argument we received; we pass it
283 through to BODY as its first argument. The caller can make
284 BODY_DATA point to anything useful that BODY might need.
650fa1ab
JB
285
286 HANDLER is a pointer to a C function to deal with a throw to TAG,
287 should one occur. We call it like this:
86327304 288 HANDLER (HANDLER_DATA, THROWN_TAG, THROW_ARGS)
650fa1ab 289 where
816a6f06
JB
290 HANDLER_DATA is the HANDLER_DATA argument we recevied; it's the
291 same idea as BODY_DATA above.
86327304
JB
292 THROWN_TAG is the tag that the user threw to; usually this is
293 TAG, but it could be something else if TAG was #t (i.e., a
294 catch-all), or the user threw to a jmpbuf.
650fa1ab 295 THROW_ARGS is the list of arguments the user passed to the THROW
4dd8323f 296 function, after the tag.
650fa1ab 297
3eed3475
JB
298 BODY_DATA is just a pointer we pass through to BODY. HANDLER_DATA
299 is just a pointer we pass through to HANDLER. We don't actually
300 use either of those pointers otherwise ourselves. The idea is
301 that, if our caller wants to communicate something to BODY or
302 HANDLER, it can pass a pointer to it as MUMBLE_DATA, which BODY and
303 HANDLER can then use. Think of it as a way to make BODY and
304 HANDLER closures, not just functions; MUMBLE_DATA points to the
305 enclosed variables.
306
307 Of course, it's up to the caller to make sure that any data a
308 MUMBLE_DATA needs is protected from GC. A common way to do this is
309 to make MUMBLE_DATA a pointer to data stored in an automatic
310 structure variable; since the collector must scan the stack for
311 references anyway, this assures that any references in MUMBLE_DATA
312 will be found. */
650fa1ab 313
0f2d19dd 314SCM
43e01b1e
NJ
315scm_c_catch (SCM tag,
316 scm_t_catch_body body, void *body_data,
317 scm_t_catch_handler handler, void *handler_data,
318 scm_t_catch_handler pre_unwind_handler, void *pre_unwind_handler_data)
0f2d19dd 319{
416f26c7
AW
320 SCM sbody, shandler, spre_unwind_handler;
321
322 sbody = make_catch_body_closure (body, body_data);
323 shandler = make_catch_handler_closure (handler, handler_data);
324 if (pre_unwind_handler)
325 spre_unwind_handler = make_catch_handler_closure (pre_unwind_handler,
326 pre_unwind_handler_data);
0f2d19dd 327 else
416f26c7
AW
328 spre_unwind_handler = SCM_UNDEFINED;
329
330 return scm_catch_with_pre_unwind_handler (tag, sbody, shandler,
331 spre_unwind_handler);
0f2d19dd
JB
332}
333
43e01b1e
NJ
334SCM
335scm_internal_catch (SCM tag,
336 scm_t_catch_body body, void *body_data,
337 scm_t_catch_handler handler, void *handler_data)
338{
416f26c7
AW
339 return scm_c_catch (tag,
340 body, body_data,
341 handler, handler_data,
342 NULL, NULL);
18eadcbe
JB
343}
344
18eadcbe 345
18eadcbe 346SCM
43e01b1e
NJ
347scm_c_with_throw_handler (SCM tag,
348 scm_t_catch_body body,
349 void *body_data,
350 scm_t_catch_handler handler,
351 void *handler_data,
352 int lazy_catch_p)
18eadcbe 353{
416f26c7 354 SCM sbody, shandler;
18eadcbe 355
e10cf6b9
AW
356 if (lazy_catch_p)
357 scm_c_issue_deprecation_warning
358 ("The LAZY_CATCH_P argument to `scm_c_with_throw_handler' is no longer.\n"
359 "supported. Instead the handler will be invoked from within the dynamic\n"
360 "context of the corresponding `throw'.\n"
361 "\nTHIS COULD CHANGE YOUR PROGRAM'S BEHAVIOR.\n\n"
362 "Please modify your program to pass 0 as the LAZY_CATCH_P argument,\n"
363 "and adapt it (if necessary) to expect to be within the dynamic context\n"
364 "of the throw.");
365
416f26c7
AW
366 sbody = make_catch_body_closure (body, body_data);
367 shandler = make_catch_handler_closure (handler, handler_data);
368
369 return scm_with_throw_handler (tag, sbody, shandler);
18eadcbe
JB
370}
371
95384717 372\f
95384717 373/* body and handler functions for use with any of the above catch variants */
18eadcbe 374
816a6f06 375/* This is a body function you can pass to scm_internal_catch if you
492960a4 376 want the body to be like Scheme's `catch' --- a thunk.
650fa1ab 377
74229f75
JB
378 BODY_DATA is a pointer to a scm_body_thunk_data structure, which
379 contains the Scheme procedure to invoke as the body, and the tag
492960a4 380 we're catching. */
650fa1ab 381
816a6f06 382SCM
6e8d25a6 383scm_body_thunk (void *body_data)
650fa1ab 384{
816a6f06 385 struct scm_body_thunk_data *c = (struct scm_body_thunk_data *) body_data;
650fa1ab 386
fdc28395 387 return scm_call_0 (c->body_proc);
650fa1ab
JB
388}
389
390
74229f75 391/* This is a handler function you can pass to scm_internal_catch if
4dd8323f
JB
392 you want the handler to act like Scheme's catch: (throw TAG ARGS ...)
393 applies a handler procedure to (TAG ARGS ...).
74229f75
JB
394
395 If the user does a throw to this catch, this function runs a
816a6f06
JB
396 handler procedure written in Scheme. HANDLER_DATA is a pointer to
397 an SCM variable holding the Scheme procedure object to invoke. It
74229f75
JB
398 ought to be a pointer to an automatic variable (i.e., one living on
399 the stack), or the procedure object should be otherwise protected
400 from GC. */
816a6f06 401SCM
6e8d25a6 402scm_handle_by_proc (void *handler_data, SCM tag, SCM throw_args)
650fa1ab 403{
816a6f06 404 SCM *handler_proc_p = (SCM *) handler_data;
650fa1ab 405
fdc28395 406 return scm_apply_1 (*handler_proc_p, tag, throw_args);
650fa1ab
JB
407}
408
1345df5d
MV
409/* SCM_HANDLE_BY_PROC_CATCHING_ALL is like SCM_HANDLE_BY_PROC but
410 catches all throws that the handler might emit itself. The handler
411 used for these `secondary' throws is SCM_HANDLE_BY_MESSAGE_NO_EXIT. */
412
413struct hbpca_data {
414 SCM proc;
415 SCM args;
416};
417
418static SCM
6e8d25a6 419hbpca_body (void *body_data)
1345df5d
MV
420{
421 struct hbpca_data *data = (struct hbpca_data *)body_data;
fdc28395 422 return scm_apply_0 (data->proc, data->args);
1345df5d
MV
423}
424
425SCM
6e8d25a6 426scm_handle_by_proc_catching_all (void *handler_data, SCM tag, SCM throw_args)
1345df5d
MV
427{
428 SCM *handler_proc_p = (SCM *) handler_data;
429 struct hbpca_data data;
430 data.proc = *handler_proc_p;
431 data.args = scm_cons (tag, throw_args);
432
433 return scm_internal_catch (SCM_BOOL_T,
434 hbpca_body, &data,
435 scm_handle_by_message_noexit, NULL);
436}
650fa1ab 437
f032b8a8
JB
438/* Derive the an exit status from the arguments to (quit ...). */
439int
6e8d25a6 440scm_exit_status (SCM args)
f032b8a8 441{
58e68be4 442 if (scm_is_pair (args))
f032b8a8
JB
443 {
444 SCM cqa = SCM_CAR (args);
445
e11e83f3
MV
446 if (scm_is_integer (cqa))
447 return (scm_to_int (cqa));
7888309b 448 else if (scm_is_false (cqa))
4765b28f 449 return EXIT_FAILURE;
58e68be4
AW
450 else
451 return EXIT_SUCCESS;
f032b8a8 452 }
58e68be4
AW
453 else if (scm_is_null (args))
454 return EXIT_SUCCESS;
455 else
456 /* A type error. Strictly speaking we shouldn't get here. */
457 return EXIT_FAILURE;
f032b8a8
JB
458}
459
74229f75 460
e0c70a8b
AW
461static int
462should_print_backtrace (SCM tag, SCM stack)
463{
464 return SCM_BACKTRACE_P
465 && scm_is_true (stack)
466 && scm_initialized_p
467 /* It's generally not useful to print backtraces for errors reading
468 or expanding code in these fallback catch statements. */
469 && !scm_is_eq (tag, scm_from_latin1_symbol ("read-error"))
470 && !scm_is_eq (tag, scm_from_latin1_symbol ("syntax-error"));
471}
472
f032b8a8
JB
473static void
474handler_message (void *handler_data, SCM tag, SCM args)
e68b42c1 475{
e0c70a8b 476 SCM p, stack, frame;
650fa1ab 477
e0c70a8b 478 p = scm_current_error_port ();
39d41afe
AW
479 /* Usually we get here via a throw to a catch-all. In that case
480 there is the throw frame active, and the catch closure, so narrow by
481 two frames. It is possible for a user to invoke
482 scm_handle_by_message directly, though, so it could be this
483 narrows too much. We'll have to see how this works out in
484 practice. */
485 stack = scm_make_stack (SCM_BOOL_T, scm_list_1 (scm_from_int (2)));
e0c70a8b 486 frame = scm_is_true (stack) ? scm_stack_ref (stack, SCM_INUM0) : SCM_BOOL_F;
eeb48bc2 487
e0c70a8b 488 if (should_print_backtrace (tag, stack))
74229f75 489 {
0607ebbf 490 scm_puts_unlocked ("Backtrace:\n", p);
e0c70a8b
AW
491 scm_display_backtrace_with_highlights (stack, p,
492 SCM_BOOL_F, SCM_BOOL_F,
493 SCM_EOL);
494 scm_newline (p);
74229f75 495 }
f64056d1 496
e0c70a8b 497 scm_print_exception (p, frame, tag, args);
f032b8a8
JB
498}
499
500
501/* This is a handler function to use if you want scheme to print a
502 message and die. Useful for dealing with throws to uncaught keys
503 at the top level.
504
505 At boot time, we establish a catch-all that uses this as its handler.
506 1) If the user wants something different, they can use (catch #t
507 ...) to do what they like.
508 2) Outside the context of a read-eval-print loop, there isn't
509 anything else good to do; libguile should not assume the existence
510 of a read-eval-print loop.
511 3) Given that we shouldn't do anything complex, it's much more
512 robust to do it in C code.
513
514 HANDLER_DATA, if non-zero, is assumed to be a char * pointing to a
515 message header to print; if zero, we use "guile" instead. That
516 text is followed by a colon, then the message described by ARGS. */
517
5a2a5407
DH
518/* Dirk:FIXME:: The name of the function should make clear that the
519 * application gets terminated.
520 */
521
f032b8a8 522SCM
6e8d25a6 523scm_handle_by_message (void *handler_data, SCM tag, SCM args)
f032b8a8 524{
4a655e50 525 if (scm_is_true (scm_eq_p (tag, scm_from_latin1_symbol ("quit"))))
9de87eea 526 exit (scm_exit_status (args));
f032b8a8
JB
527
528 handler_message (handler_data, tag, args);
9de87eea 529 scm_i_pthread_exit (NULL);
23f2b9a3
KR
530
531 /* this point not reached, but suppress gcc warning about no return value
532 in case scm_i_pthread_exit isn't marked as "noreturn" (which seemed not
533 to be the case on cygwin for instance) */
534 return SCM_BOOL_F;
74229f75
JB
535}
536
537
f032b8a8
JB
538/* This is just like scm_handle_by_message, but it doesn't exit; it
539 just returns #f. It's useful in cases where you don't really know
540 enough about the body to handle things in a better way, but don't
541 want to let throws fall off the bottom of the wind list. */
542SCM
6e8d25a6 543scm_handle_by_message_noexit (void *handler_data, SCM tag, SCM args)
74229f75 544{
4a655e50 545 if (scm_is_true (scm_eq_p (tag, scm_from_latin1_symbol ("quit"))))
9de87eea
MV
546 exit (scm_exit_status (args));
547
f032b8a8
JB
548 handler_message (handler_data, tag, args);
549
550 return SCM_BOOL_F;
e68b42c1
MD
551}
552
3eed3475 553
e158e4f4 554SCM
e81d98ec 555scm_handle_by_throw (void *handler_data SCM_UNUSED, SCM tag, SCM args)
e158e4f4
MD
556{
557 scm_ithrow (tag, args, 1);
558 return SCM_UNSPECIFIED; /* never returns */
559}
560
43e01b1e 561SCM
36c40440 562scm_ithrow (SCM key, SCM args, int no_return SCM_UNUSED)
ad310508 563{
416f26c7 564 return scm_throw (key, args);
ad310508
MD
565}
566
7e2fd4e7 567SCM_SYMBOL (scm_stack_overflow_key, "stack-overflow");
c6a32a2c 568
7e2fd4e7
AW
569void
570scm_report_stack_overflow (void)
5a588521 571{
7e2fd4e7 572 /* Arguments as if from:
5a588521 573
7e2fd4e7 574 scm_error (stack-overflow, NULL, "Stack overflow", #f, #f);
5a588521 575
7e2fd4e7
AW
576 We build the arguments manually because we throw without running
577 pre-unwind handlers. (Pre-unwind handlers could rewind the
578 stack.) */
579 SCM args = scm_list_4 (SCM_BOOL_F,
580 scm_from_latin1_string ("Stack overflow"),
581 SCM_BOOL_F,
582 SCM_BOOL_F);
583 throw_without_pre_unwind (scm_stack_overflow_key, args);
cd4f274c 584
7e2fd4e7
AW
585 /* Not reached. */
586 abort ();
416f26c7 587}
0f2d19dd 588
0f2d19dd
JB
589void
590scm_init_throw ()
0f2d19dd 591{
416f26c7
AW
592 tc16_catch_closure = scm_make_smob_type ("catch-closure", 0);
593 scm_set_smob_apply (tc16_catch_closure, apply_catch_closure, 0, 0, 1);
e841c3e0 594
5d20fd49
AW
595 exception_handler_fluid = scm_make_fluid_with_default (SCM_BOOL_F);
596 /* This binding is later removed when the Scheme definitions of catch,
597 throw, and with-throw-handler are created in boot-9.scm. */
598 scm_c_define ("%exception-handler", exception_handler_fluid);
599
7e2fd4e7 600 scm_c_define ("catch", scm_c_make_gsubr ("catch", 3, 1, 0, catch));
60617d81 601 throw_var = scm_c_define ("throw", scm_c_make_gsubr ("throw", 1, 0, 1,
7e2fd4e7 602 throw_without_pre_unwind));
e841c3e0 603
a0599745 604#include "libguile/throw.x"
0f2d19dd 605}
89e00824
ML
606
607/*
608 Local Variables:
609 c-file-style: "gnu"
610 End:
611*/