1 /* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program 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
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
51 #include "backtrace.h"
52 #ifdef DEBUG_EXTENSIONS
55 #include "continuations.h"
63 /* the jump buffer data structure */
64 static int scm_tc16_jmpbuffer
;
66 #define SCM_JMPBUFP(O) (SCM_TYP16(O) == scm_tc16_jmpbuffer)
67 #define JBACTIVE(O) (SCM_CAR (O) & (1L << 16L))
68 #define ACTIVATEJB(O) (SCM_SETOR_CAR (O, (1L << 16L)))
69 #define DEACTIVATEJB(O) (SCM_SETAND_CAR (O, ~(1L << 16L)))
71 #ifndef DEBUG_EXTENSIONS
72 #define JBJMPBUF(O) ((jmp_buf*)SCM_CDR (O) )
73 #define SETJBJMPBUF SCM_SETCDR
75 #define SCM_JBDFRAME(O) ((scm_debug_frame*)SCM_CAR (SCM_CDR (O)) )
76 #define JBJMPBUF(O) ((jmp_buf*)SCM_CDR (SCM_CDR (O)) )
77 #define SCM_SETJBDFRAME(O,X) SCM_SETCAR (SCM_CDR (O), (SCM)(X))
78 #define SETJBJMPBUF(O,X) SCM_SETCDR(SCM_CDR (O), X)
80 static scm_sizet freejb
SCM_P ((SCM jbsmob
));
86 scm_must_free ((char *) SCM_CDR (jbsmob
));
87 return sizeof (scm_cell
);
91 static int printjb
SCM_P ((SCM exp
, SCM port
, scm_print_state
*pstate
));
93 printjb (exp
, port
, pstate
)
96 scm_print_state
*pstate
;
98 scm_puts ("#<jmpbuffer ", port
);
99 scm_puts (JBACTIVE(exp
) ? "(active) " : "(inactive) ", port
);
100 scm_intprint((SCM
) JBJMPBUF(exp
), 16, port
);
101 scm_putc ('>', port
);
105 static scm_smobfuns jbsmob
= {
107 #ifdef DEBUG_EXTENSIONS
116 static SCM make_jmpbuf
SCM_P ((void));
121 SCM_NEWCELL (answer
);
124 #ifdef DEBUG_EXTENSIONS
125 char *mem
= scm_must_malloc (sizeof (scm_cell
), "jb");
126 SCM_SETCDR (answer
, (SCM
) mem
);
128 SCM_SETCAR (answer
, scm_tc16_jmpbuffer
);
129 SETJBJMPBUF(answer
, (jmp_buf *)0);
130 DEACTIVATEJB(answer
);
137 /* scm_internal_catch (the guts of catch) */
139 struct jmp_buf_and_retval
/* use only on the stack, in scm_catch */
141 jmp_buf buf
; /* must be first */
147 /* scm_internal_catch is the guts of catch. It handles all the
148 mechanics of setting up a catch target, invoking the catch body,
149 and perhaps invoking the handler if the body does a throw.
151 The function is designed to be usable from C code, but is general
152 enough to implement all the semantics Guile Scheme expects from
155 TAG is the catch tag. Typically, this is a symbol, but this
156 function doesn't actually care about that.
158 BODY is a pointer to a C function which runs the body of the catch;
159 this is the code you can throw from. We call it like this:
160 BODY (BODY_DATA, JMPBUF)
162 BODY_DATA is just the BODY_DATA argument we received; we pass it
163 through to BODY as its first argument. The caller can make
164 BODY_DATA point to anything useful that BODY might need.
165 JMPBUF is the Scheme jmpbuf object corresponding to this catch,
166 which we have just created and initialized.
168 HANDLER is a pointer to a C function to deal with a throw to TAG,
169 should one occur. We call it like this:
170 HANDLER (HANDLER_DATA, THROWN_TAG, THROW_ARGS)
172 HANDLER_DATA is the HANDLER_DATA argument we recevied; it's the
173 same idea as BODY_DATA above.
174 THROWN_TAG is the tag that the user threw to; usually this is
175 TAG, but it could be something else if TAG was #t (i.e., a
176 catch-all), or the user threw to a jmpbuf.
177 THROW_ARGS is the list of arguments the user passed to the THROW
178 function, after the tag.
180 BODY_DATA is just a pointer we pass through to BODY. HANDLER_DATA
181 is just a pointer we pass through to HANDLER. We don't actually
182 use either of those pointers otherwise ourselves. The idea is
183 that, if our caller wants to communicate something to BODY or
184 HANDLER, it can pass a pointer to it as MUMBLE_DATA, which BODY and
185 HANDLER can then use. Think of it as a way to make BODY and
186 HANDLER closures, not just functions; MUMBLE_DATA points to the
189 Of course, it's up to the caller to make sure that any data a
190 MUMBLE_DATA needs is protected from GC. A common way to do this is
191 to make MUMBLE_DATA a pointer to data stored in an automatic
192 structure variable; since the collector must scan the stack for
193 references anyway, this assures that any references in MUMBLE_DATA
197 scm_internal_catch (tag
, body
, body_data
, handler
, handler_data
)
199 scm_catch_body_t body
;
201 scm_catch_handler_t handler
;
204 struct jmp_buf_and_retval jbr
;
208 jmpbuf
= make_jmpbuf ();
210 scm_dynwinds
= scm_acons (tag
, jmpbuf
, scm_dynwinds
);
211 SETJBJMPBUF(jmpbuf
, &jbr
.buf
);
212 #ifdef DEBUG_EXTENSIONS
213 SCM_SETJBDFRAME(jmpbuf
, scm_last_debug_frame
);
215 if (setjmp (jbr
.buf
))
220 #ifdef STACK_CHECKING
221 scm_stack_checking_enabled_p
= SCM_STACK_CHECKING_P
;
224 DEACTIVATEJB (jmpbuf
);
225 scm_dynwinds
= SCM_CDR (scm_dynwinds
);
227 throw_args
= jbr
.retval
;
228 throw_tag
= jbr
.throw_tag
;
229 jbr
.throw_tag
= SCM_EOL
;
230 jbr
.retval
= SCM_EOL
;
231 answer
= handler (handler_data
, throw_tag
, throw_args
);
236 answer
= body (body_data
);
238 DEACTIVATEJB (jmpbuf
);
239 scm_dynwinds
= SCM_CDR (scm_dynwinds
);
247 /* scm_internal_lazy_catch (the guts of lazy catching) */
249 /* The smob tag for lazy_catch smobs. */
250 static long tc16_lazy_catch
;
252 /* This is the structure we put on the wind list for a lazy catch. It
253 stores the handler function to call, and the data pointer to pass
254 through to it. It's not a Scheme closure, but it is a function
255 with data, so the term "closure" is appropriate in its broader
258 (We don't need anything like this in the "eager" catch code,
259 because the same C frame runs both the body and the handler.) */
261 scm_catch_handler_t handler
;
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... */
270 print_lazy_catch (SCM closure
, SCM port
, scm_print_state
*pstate
)
272 struct lazy_catch
*c
= (struct lazy_catch
*) SCM_CDR (closure
);
275 sprintf (buf
, "#<lazy-catch 0x%lx 0x%lx>",
276 (long) c
->handler
, (long) c
->handler_data
);
277 scm_puts (buf
, port
);
282 static scm_smobfuns lazy_catch_funs
= {
283 scm_mark0
, scm_free0
, print_lazy_catch
, 0
287 /* Given a pointer to a lazy catch structure, return a smob for it,
288 suitable for inclusion in the wind list. ("Ah yes, a Château
289 Gollombiere '72, non?"). */
291 make_lazy_catch (struct lazy_catch
*c
)
296 SCM_SETCDR (smob
, c
);
297 SCM_SETCAR (smob
, tc16_lazy_catch
);
302 #define SCM_LAZY_CATCH_P(obj) \
303 (SCM_NIMP (obj) && (SCM_CAR (obj) == tc16_lazy_catch))
306 /* Exactly like scm_internal_catch, except:
307 - It does not unwind the stack (this is the major difference).
308 - If handler returns, its value is returned from the throw. */
310 scm_internal_lazy_catch (tag
, body
, body_data
, handler
, handler_data
)
312 scm_catch_body_t body
;
314 scm_catch_handler_t handler
;
317 SCM lazy_catch
, answer
;
321 c
.handler_data
= handler_data
;
322 lazy_catch
= make_lazy_catch (&c
);
325 scm_dynwinds
= scm_acons (tag
, lazy_catch
, scm_dynwinds
);
328 answer
= (*body
) (body_data
);
331 scm_dynwinds
= SCM_CDR (scm_dynwinds
);
338 /* scm_internal_stack_catch
339 Use this one if you want debugging information to be stored in
340 scm_the_last_stack_fluid on error. */
343 ss_handler (void *data
, SCM tag
, SCM throw_args
)
346 scm_fluid_set_x (SCM_CDR (scm_the_last_stack_fluid
),
347 scm_make_stack (scm_cons (SCM_BOOL_T
, SCM_EOL
)));
348 /* Throw the error */
349 return scm_throw (tag
, throw_args
);
355 scm_catch_body_t body
;
360 cwss_body (void *data
)
362 struct cwss_data
*d
= data
;
363 return scm_internal_lazy_catch (d
->tag
, d
->body
, d
->data
, ss_handler
, NULL
);
367 scm_internal_stack_catch (SCM tag
,
368 scm_catch_body_t body
,
370 scm_catch_handler_t handler
,
377 return scm_internal_catch (tag
, cwss_body
, &d
, handler
, handler_data
);
382 /* body and handler functions for use with any of the above catch variants */
384 /* This is a body function you can pass to scm_internal_catch if you
385 want the body to be like Scheme's `catch' --- a thunk.
387 BODY_DATA is a pointer to a scm_body_thunk_data structure, which
388 contains the Scheme procedure to invoke as the body, and the tag
392 scm_body_thunk (body_data
)
395 struct scm_body_thunk_data
*c
= (struct scm_body_thunk_data
*) body_data
;
397 return scm_apply (c
->body_proc
, SCM_EOL
, SCM_EOL
);
401 /* This is a handler function you can pass to scm_internal_catch if
402 you want the handler to act like Scheme's catch: (throw TAG ARGS ...)
403 applies a handler procedure to (TAG ARGS ...).
405 If the user does a throw to this catch, this function runs a
406 handler procedure written in Scheme. HANDLER_DATA is a pointer to
407 an SCM variable holding the Scheme procedure object to invoke. It
408 ought to be a pointer to an automatic variable (i.e., one living on
409 the stack), or the procedure object should be otherwise protected
412 scm_handle_by_proc (handler_data
, tag
, throw_args
)
417 SCM
*handler_proc_p
= (SCM
*) handler_data
;
419 return scm_apply (*handler_proc_p
, scm_cons (tag
, throw_args
), SCM_EOL
);
422 /* SCM_HANDLE_BY_PROC_CATCHING_ALL is like SCM_HANDLE_BY_PROC but
423 catches all throws that the handler might emit itself. The handler
424 used for these `secondary' throws is SCM_HANDLE_BY_MESSAGE_NO_EXIT. */
432 hbpca_body (body_data
)
435 struct hbpca_data
*data
= (struct hbpca_data
*)body_data
;
436 return scm_apply (data
->proc
, data
->args
, SCM_EOL
);
440 scm_handle_by_proc_catching_all (handler_data
, tag
, throw_args
)
445 SCM
*handler_proc_p
= (SCM
*) handler_data
;
446 struct hbpca_data data
;
447 data
.proc
= *handler_proc_p
;
448 data
.args
= scm_cons (tag
, throw_args
);
450 return scm_internal_catch (SCM_BOOL_T
,
452 scm_handle_by_message_noexit
, NULL
);
455 /* Derive the an exit status from the arguments to (quit ...). */
457 scm_exit_status (args
)
460 if (SCM_NNULLP (args
))
462 SCM cqa
= SCM_CAR (args
);
465 return (SCM_INUM (cqa
));
466 else if (SCM_FALSEP (cqa
))
474 handler_message (void *handler_data
, SCM tag
, SCM args
)
476 char *prog_name
= (char *) handler_data
;
477 SCM p
= scm_cur_errp
;
482 scm_puts (prog_name
, p
);
485 if (scm_ilength (args
) >= 3)
487 SCM message
= SCM_CADR (args
);
488 SCM parts
= SCM_CADDR (args
);
490 scm_display_error_message (message
, parts
, p
);
494 scm_puts ("uncaught throw to ", p
);
495 scm_prin1 (tag
, p
, 0);
497 scm_prin1 (args
, p
, 1);
503 /* This is a handler function to use if you want scheme to print a
504 message and die. Useful for dealing with throws to uncaught keys
507 At boot time, we establish a catch-all that uses this as its handler.
508 1) If the user wants something different, they can use (catch #t
509 ...) to do what they like.
510 2) Outside the context of a read-eval-print loop, there isn't
511 anything else good to do; libguile should not assume the existence
512 of a read-eval-print loop.
513 3) Given that we shouldn't do anything complex, it's much more
514 robust to do it in C code.
516 HANDLER_DATA, if non-zero, is assumed to be a char * pointing to a
517 message header to print; if zero, we use "guile" instead. That
518 text is followed by a colon, then the message described by ARGS. */
521 scm_handle_by_message (handler_data
, tag
, args
)
526 if (SCM_NFALSEP (scm_eq_p (tag
, SCM_CAR (scm_intern0 ("quit")))))
527 exit (scm_exit_status (args
));
529 handler_message (handler_data
, tag
, args
);
535 /* This is just like scm_handle_by_message, but it doesn't exit; it
536 just returns #f. It's useful in cases where you don't really know
537 enough about the body to handle things in a better way, but don't
538 want to let throws fall off the bottom of the wind list. */
540 scm_handle_by_message_noexit (handler_data
, tag
, args
)
545 handler_message (handler_data
, tag
, args
);
552 scm_handle_by_throw (handler_data
, tag
, args
)
557 scm_ithrow (tag
, args
, 1);
558 return SCM_UNSPECIFIED
; /* never returns */
563 /* the Scheme-visible CATCH and LAZY-CATCH functions */
565 SCM_PROC(s_catch
, "catch", 3, 0, 0, scm_catch
);
567 scm_catch (tag
, thunk
, handler
)
572 struct scm_body_thunk_data c
;
574 SCM_ASSERT ((SCM_NIMP(tag
) && SCM_SYMBOLP(tag
)) || tag
== SCM_BOOL_T
,
582 /* scm_internal_catch takes care of all the mechanics of setting up
583 a catch tag; we tell it to call scm_body_thunk to run the body,
584 and scm_handle_by_proc to deal with any throws to this catch.
585 The former receives a pointer to c, telling it how to behave.
586 The latter receives a pointer to HANDLER, so it knows who to call. */
587 return scm_internal_catch (tag
,
589 scm_handle_by_proc
, &handler
);
593 SCM_PROC(s_lazy_catch
, "lazy-catch", 3, 0, 0, scm_lazy_catch
);
595 scm_lazy_catch (tag
, thunk
, handler
)
600 struct scm_body_thunk_data c
;
602 SCM_ASSERT ((SCM_NIMP(tag
) && SCM_SYMBOLP(tag
))
603 || (tag
== SCM_BOOL_T
),
604 tag
, SCM_ARG1
, s_lazy_catch
);
609 /* scm_internal_lazy_catch takes care of all the mechanics of
610 setting up a lazy catch tag; we tell it to call scm_body_thunk to
611 run the body, and scm_handle_by_proc to deal with any throws to
612 this catch. The former receives a pointer to c, telling it how
613 to behave. The latter receives a pointer to HANDLER, so it knows
615 return scm_internal_lazy_catch (tag
,
617 scm_handle_by_proc
, &handler
);
624 SCM_PROC(s_throw
, "throw", 1, 0, 1, scm_throw
);
626 scm_throw (key
, args
)
630 SCM_ASSERT (SCM_NIMP (key
) && SCM_SYMBOLP (key
), key
, SCM_ARG1
, s_throw
);
631 /* May return if handled by lazy catch. */
632 return scm_ithrow (key
, args
, 1);
637 scm_ithrow (key
, args
, noreturn
)
645 SCM dynpair
= SCM_UNDEFINED
;
648 /* Search the wind list for an appropriate catch.
649 "Waiter, please bring us the wind list." */
650 for (winds
= scm_dynwinds
; SCM_NIMP (winds
); winds
= SCM_CDR (winds
))
652 if (! SCM_CONSP (winds
))
655 dynpair
= SCM_CAR (winds
);
656 if (SCM_NIMP (dynpair
) && SCM_CONSP (dynpair
))
658 SCM this_key
= SCM_CAR (dynpair
);
660 if (this_key
== SCM_BOOL_T
|| this_key
== key
)
665 /* If we didn't find anything, abort. scm_boot_guile should
666 have established a catch-all, but obviously things are
667 thoroughly screwed up. */
668 if (winds
== SCM_EOL
)
671 /* If the wind list is malformed, bail. */
672 if (SCM_IMP (winds
) || SCM_NCONSP (winds
))
675 if (dynpair
!= SCM_BOOL_F
)
676 jmpbuf
= SCM_CDR (dynpair
);
680 return SCM_UNSPECIFIED
;
683 scm_exitval
= scm_cons (key
, args
);
684 scm_dowinds (SCM_EOL
, scm_ilength (scm_dynwinds
));
685 #ifdef DEBUG_EXTENSIONS
686 scm_last_debug_frame
= SCM_DFRAME (scm_rootcont
);
688 longjmp (SCM_JMPBUF (scm_rootcont
), 1);
692 for (wind_goal
= scm_dynwinds
;
693 SCM_CDAR (wind_goal
) != jmpbuf
;
694 wind_goal
= SCM_CDR (wind_goal
))
697 /* Is a lazy catch? In wind list entries for lazy catches, the key
698 is bound to a lazy_catch smob, not a jmpbuf. */
699 if (SCM_LAZY_CATCH_P (jmpbuf
))
701 struct lazy_catch
*c
= (struct lazy_catch
*) SCM_CDR (jmpbuf
);
702 SCM oldwinds
= scm_dynwinds
;
704 scm_dowinds (wind_goal
, (scm_ilength (scm_dynwinds
)
705 - scm_ilength (wind_goal
)));
707 handle
= scm_dynwinds
;
708 scm_dynwinds
= SCM_CDR (scm_dynwinds
);
710 answer
= (c
->handler
) (c
->handler_data
, key
, args
);
712 SCM_SETCDR (handle
, scm_dynwinds
);
713 scm_dynwinds
= handle
;
715 scm_dowinds (oldwinds
, (scm_ilength (scm_dynwinds
)
716 - scm_ilength (oldwinds
)));
720 /* Otherwise, it's a normal catch. */
721 else if (SCM_JMPBUFP (jmpbuf
))
723 struct jmp_buf_and_retval
* jbr
;
724 scm_dowinds (wind_goal
, (scm_ilength (scm_dynwinds
)
725 - scm_ilength (wind_goal
)));
726 jbr
= (struct jmp_buf_and_retval
*)JBJMPBUF (jmpbuf
);
727 jbr
->throw_tag
= key
;
731 /* Otherwise, it's some random piece of junk. */
735 #ifdef DEBUG_EXTENSIONS
736 scm_last_debug_frame
= SCM_JBDFRAME (jmpbuf
);
738 longjmp (*JBJMPBUF (jmpbuf
), 1);
745 scm_tc16_jmpbuffer
= scm_newsmob (&jbsmob
);
746 tc16_lazy_catch
= scm_newsmob (&lazy_catch_funs
);