123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- /* Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #if HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* This blob per the Autoconf manual (under "Particular Functions"), updated
- to match that of Gnulib. */
- #ifndef alloca
- # if HAVE_ALLOCA_H
- # include <alloca.h>
- # elif defined __GNUC__
- # define alloca __builtin_alloca
- # elif defined _AIX
- # define alloca __alloca
- # elif defined _MSC_VER
- # include <malloc.h>
- # define alloca _alloca
- # else
- # include <stddef.h>
- # ifdef __cplusplus
- extern "C"
- # endif
- void *alloca (size_t);
- # endif
- #endif
- #include <libguile.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #ifdef HAVE_STRING_H
- # include <string.h>
- #endif
- void set_flag (void *data);
- void func1 (void);
- void func2 (void);
- void func3 (void);
- void func4 (void);
- void check_flag1 (const char *msg, void (*func)(void), int val);
- SCM check_flag1_body (void *data);
- SCM return_tag (void *data, SCM tag, SCM args);
- void check_cont (int rewindable);
- SCM check_cont_body (void *data);
- void close_port (SCM port);
- void delete_file (void *data);
- void check_ports (void);
- void check_fluid (void);
- int flag1, flag2, flag3;
- void
- set_flag (void *data)
- {
- int *f = (int *)data;
- *f = 1;
- }
- /* FUNC1 should leave flag1 zero.
- */
- void
- func1 ()
- {
- scm_dynwind_begin (0);
- flag1 = 0;
- scm_dynwind_unwind_handler (set_flag, &flag1, 0);
- scm_dynwind_end ();
- }
- /* FUNC2 should set flag1.
- */
- void
- func2 ()
- {
- scm_dynwind_begin (0);
- flag1 = 0;
- scm_dynwind_unwind_handler (set_flag, &flag1, SCM_F_WIND_EXPLICITLY);
- scm_dynwind_end ();
- }
- /* FUNC3 should set flag1.
- */
- void
- func3 ()
- {
- scm_dynwind_begin (0);
- flag1 = 0;
- scm_dynwind_unwind_handler (set_flag, &flag1, 0);
- scm_misc_error ("func3", "gratuitous error", SCM_EOL);
- scm_dynwind_end ();
- }
- /* FUNC4 should set flag1.
- */
- void
- func4 ()
- {
- scm_dynwind_begin (0);
- flag1 = 0;
- scm_dynwind_unwind_handler (set_flag, &flag1, SCM_F_WIND_EXPLICITLY);
- scm_misc_error ("func4", "gratuitous error", SCM_EOL);
- scm_dynwind_end ();
- }
- SCM
- check_flag1_body (void *data)
- {
- void (*f)(void) = (void (*)(void))data;
- f ();
- return SCM_UNSPECIFIED;
- }
- SCM
- return_tag (void *data, SCM tag, SCM args)
- {
- return tag;
- }
- void
- check_flag1 (const char *tag, void (*func)(void), int val)
- {
- scm_internal_catch (SCM_BOOL_T,
- check_flag1_body, func,
- return_tag, NULL);
- if (flag1 != val)
- {
- printf ("%s failed\n", tag);
- exit (1);
- }
- }
- SCM
- check_cont_body (void *data)
- {
- scm_t_dynwind_flags flags = (data? SCM_F_DYNWIND_REWINDABLE : 0);
- int first;
- SCM val;
- scm_dynwind_begin (flags);
- val = scm_make_continuation (&first);
- scm_dynwind_end ();
- return val;
- }
- void
- check_cont (int rewindable)
- {
- SCM res;
-
- res = scm_internal_catch (SCM_BOOL_T,
- check_cont_body, (void *)(long)rewindable,
- return_tag, NULL);
- /* RES is now either the created continuation, the value passed to
- the continuation, or a catch-tag, such as 'misc-error.
- */
- if (scm_is_true (scm_procedure_p (res)))
- {
- /* a continuation, invoke it */
- scm_call_1 (res, SCM_BOOL_F);
- }
- else if (scm_is_false (res))
- {
- /* the result of invoking the continuation, dynwind must be
- rewindable */
- if (rewindable)
- return;
- printf ("continuation not blocked\n");
- exit (1);
- }
- else
- {
- /* the catch tag, dynwind must not have been rewindable. */
- if (!rewindable)
- return;
- printf ("continuation didn't work\n");
- exit (1);
- }
- }
- void
- close_port (SCM port)
- {
- scm_close_port (port);
- }
- void
- delete_file (void *data)
- {
- unlink ((char *)data);
- }
- void
- check_ports ()
- {
- #define FILENAME_TEMPLATE "/check-ports.XXXXXX"
- char *filename;
- const char *tmpdir = getenv ("TMPDIR");
- if (tmpdir == NULL)
- tmpdir = "/tmp";
- filename = (char *) alloca (strlen (tmpdir) +
- sizeof (FILENAME_TEMPLATE) + 1);
- strcpy (filename, tmpdir);
- strcat (filename, FILENAME_TEMPLATE);
- if (mktemp (filename) == NULL)
- exit (1);
- scm_dynwind_begin (0);
- {
- SCM port = scm_open_file (scm_from_locale_string (filename),
- scm_from_locale_string ("w"));
- scm_dynwind_unwind_handler_with_scm (close_port, port,
- SCM_F_WIND_EXPLICITLY);
- scm_dynwind_current_output_port (port);
- scm_write (scm_version (), SCM_UNDEFINED);
- }
- scm_dynwind_end ();
- scm_dynwind_begin (0);
- {
- SCM port = scm_open_file (scm_from_locale_string (filename),
- scm_from_locale_string ("r"));
- SCM res;
- scm_dynwind_unwind_handler_with_scm (close_port, port,
- SCM_F_WIND_EXPLICITLY);
- scm_dynwind_unwind_handler (delete_file, filename, SCM_F_WIND_EXPLICITLY);
- scm_dynwind_current_input_port (port);
- res = scm_read (SCM_UNDEFINED);
- if (scm_is_false (scm_equal_p (res, scm_version ())))
- {
- printf ("ports didn't work\n");
- exit (1);
- }
- }
- scm_dynwind_end ();
- #undef FILENAME_TEMPLATE
- }
- void
- check_fluid ()
- {
- SCM f = scm_make_fluid ();
- SCM x;
- scm_fluid_set_x (f, scm_from_int (12));
- scm_dynwind_begin (0);
- scm_dynwind_fluid (f, scm_from_int (13));
- x = scm_fluid_ref (f);
- scm_dynwind_end ();
- if (!scm_is_eq (x, scm_from_int (13)))
- {
- printf ("setting fluid didn't work\n");
- exit (1);
- }
- if (!scm_is_eq (scm_fluid_ref (f), scm_from_int (12)))
- {
- printf ("resetting fluid didn't work\n");
- exit (1);
- }
- }
- static void
- inner_main (void *data, int argc, char **argv)
- {
- check_flag1 ("func1", func1, 0);
- check_flag1 ("func2", func2, 1);
- check_flag1 ("func3", func3, 1);
- check_flag1 ("func4", func4, 1);
- check_cont (0);
- check_cont (1);
- check_ports ();
- check_fluid ();
- exit (0);
- }
- int
- main (int argc, char **argv)
- {
- scm_boot_guile (argc, argv, inner_main, 0);
- return 0;
- }
|