1 /* Copyright (C) 2004, 2005, 2008, 2009, 2010, 2013 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
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.
8 * This library is distributed in the hope that it will be useful, but
9 * 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.
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
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35 void set_flag (void *data
);
40 void check_flag1 (const char *msg
, void (*func
)(void), int val
);
41 SCM
check_flag1_body (void *data
);
42 SCM
return_tag (void *data
, SCM tag
, SCM args
);
43 void check_cont (int rewindable
);
44 SCM
check_cont_body (void *data
);
45 void close_port (SCM port
);
46 void delete_file (void *data
);
47 void check_ports (void);
48 void check_fluid (void);
50 int flag1
, flag2
, flag3
;
59 /* FUNC1 should leave flag1 zero.
65 scm_dynwind_begin (0);
67 scm_dynwind_unwind_handler (set_flag
, &flag1
, 0);
71 /* FUNC2 should set flag1.
77 scm_dynwind_begin (0);
79 scm_dynwind_unwind_handler (set_flag
, &flag1
, SCM_F_WIND_EXPLICITLY
);
83 /* FUNC3 should set flag1.
89 scm_dynwind_begin (0);
91 scm_dynwind_unwind_handler (set_flag
, &flag1
, 0);
92 scm_misc_error ("func3", "gratuitous error", SCM_EOL
);
96 /* FUNC4 should set flag1.
102 scm_dynwind_begin (0);
104 scm_dynwind_unwind_handler (set_flag
, &flag1
, SCM_F_WIND_EXPLICITLY
);
105 scm_misc_error ("func4", "gratuitous error", SCM_EOL
);
110 check_flag1_body (void *data
)
112 void (*f
)(void) = (void (*)(void))data
;
114 return SCM_UNSPECIFIED
;
118 return_tag (void *data
, SCM tag
, SCM args
)
124 check_flag1 (const char *tag
, void (*func
)(void), int val
)
126 scm_internal_catch (SCM_BOOL_T
,
127 check_flag1_body
, func
,
131 printf ("%s failed\n", tag
);
137 check_cont_body (void *data
)
139 scm_t_dynwind_flags flags
= (data
? SCM_F_DYNWIND_REWINDABLE
: 0);
142 scm_dynwind_begin (flags
);
143 val
= scm_c_eval_string ("(call/cc (lambda (k) k))");
149 check_cont (int rewindable
)
153 res
= scm_internal_catch (SCM_BOOL_T
,
154 check_cont_body
, (void *)(long)rewindable
,
157 /* RES is now either the created continuation, the value passed to
158 the continuation, or a catch-tag, such as 'misc-error.
161 if (scm_is_true (scm_procedure_p (res
)))
163 /* a continuation, invoke it */
164 scm_call_1 (res
, SCM_BOOL_F
);
166 else if (scm_is_false (res
))
168 /* the result of invoking the continuation, dynwind must be
172 printf ("continuation not blocked\n");
177 /* the catch tag, dynwind must not have been rewindable. */
180 printf ("continuation didn't work\n");
186 close_port (SCM port
)
188 scm_close_port (port
);
192 delete_file (void *data
)
194 unlink ((char *)data
);
200 #define FILENAME_TEMPLATE "/check-ports.XXXXXX"
202 const char *tmpdir
= getenv ("TMPDIR");
204 extern int mkstemp (char *);
206 /* On Windows neither $TMPDIR nor /tmp can be relied on. */
208 tmpdir
= getenv ("TEMP");
210 tmpdir
= getenv ("TMP");
218 filename
= alloca (strlen (tmpdir
) + sizeof (FILENAME_TEMPLATE
) + 1);
219 strcpy (filename
, tmpdir
);
220 strcat (filename
, FILENAME_TEMPLATE
);
222 /* Sanity check: Make sure that `filename' is actually writeable.
223 We used to use mktemp(3), but that is now considered a security risk. */
224 if (0 > mkstemp (filename
))
227 scm_dynwind_begin (0);
229 SCM port
= scm_open_file (scm_from_locale_string (filename
),
230 scm_from_locale_string ("w"));
231 scm_dynwind_unwind_handler_with_scm (close_port
, port
,
232 SCM_F_WIND_EXPLICITLY
);
234 scm_dynwind_current_output_port (port
);
235 scm_write (scm_version (), SCM_UNDEFINED
);
239 scm_dynwind_begin (0);
241 SCM port
= scm_open_file (scm_from_locale_string (filename
),
242 scm_from_locale_string ("r"));
244 scm_dynwind_unwind_handler_with_scm (close_port
, port
,
245 SCM_F_WIND_EXPLICITLY
);
246 scm_dynwind_unwind_handler (delete_file
, filename
, SCM_F_WIND_EXPLICITLY
);
248 scm_dynwind_current_input_port (port
);
249 res
= scm_read (SCM_UNDEFINED
);
250 if (scm_is_false (scm_equal_p (res
, scm_version ())))
252 printf ("ports didn't work\n");
257 #undef FILENAME_TEMPLATE
263 SCM f
= scm_make_fluid ();
266 scm_fluid_set_x (f
, scm_from_int (12));
268 scm_dynwind_begin (0);
269 scm_dynwind_fluid (f
, scm_from_int (13));
270 x
= scm_fluid_ref (f
);
273 if (!scm_is_eq (x
, scm_from_int (13)))
275 printf ("setting fluid didn't work\n");
279 if (!scm_is_eq (scm_fluid_ref (f
), scm_from_int (12)))
281 printf ("resetting fluid didn't work\n");
287 inner_main (void *data
, int argc
, char **argv
)
289 check_flag1 ("func1", func1
, 0);
290 check_flag1 ("func2", func2
, 1);
291 check_flag1 ("func3", func3
, 1);
292 check_flag1 ("func4", func4
, 1);
305 main (int argc
, char **argv
)
307 scm_boot_guile (argc
, argv
, inner_main
, 0);