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