Commit | Line | Data |
---|---|---|
3c8fb18e MV |
1 | #include <libguile.h> |
2 | #include <stdlib.h> | |
3 | #include <stdio.h> | |
c05d0e8f | 4 | #include <unistd.h> |
3c8fb18e MV |
5 | |
6 | void set_flag (void *data); | |
7 | void func1 (void); | |
8 | void func2 (void); | |
9 | void func3 (void); | |
10 | void func4 (void); | |
11 | void check_flag1 (const char *msg, void (*func)(void), int val); | |
12 | SCM check_flag1_body (void *data); | |
13 | SCM return_tag (void *data, SCM tag, SCM args); | |
14 | void check_cont (int rewindable); | |
15 | SCM check_cont_body (void *data); | |
c05d0e8f MV |
16 | void close_port (SCM port); |
17 | void delete_file (void *data); | |
18 | void check_ports (void); | |
3c8fb18e MV |
19 | |
20 | int flag1, flag2, flag3; | |
21 | ||
22 | void | |
23 | set_flag (void *data) | |
24 | { | |
25 | int *f = (int *)data; | |
26 | *f = 1; | |
27 | } | |
28 | ||
29 | /* FUNC1 should leave flag1 zero. | |
30 | */ | |
31 | ||
32 | void | |
33 | func1 () | |
34 | { | |
35 | scm_begin_frame (0); | |
36 | flag1 = 0; | |
37 | scm_on_unwind (set_flag, &flag1, 0); | |
38 | scm_end_frame (); | |
39 | } | |
40 | ||
41 | /* FUNC2 should set flag1. | |
42 | */ | |
43 | ||
44 | void | |
45 | func2 () | |
46 | { | |
47 | scm_begin_frame (0); | |
48 | flag1 = 0; | |
c05d0e8f | 49 | scm_on_unwind (set_flag, &flag1, SCM_F_WIND_EXPLICITLY); |
3c8fb18e MV |
50 | scm_end_frame (); |
51 | } | |
52 | ||
53 | /* FUNC3 should set flag1. | |
54 | */ | |
55 | ||
56 | void | |
57 | func3 () | |
58 | { | |
59 | scm_begin_frame (0); | |
60 | flag1 = 0; | |
61 | scm_on_unwind (set_flag, &flag1, 0); | |
62 | scm_misc_error ("func3", "gratuitous error", SCM_EOL); | |
63 | scm_end_frame (); | |
64 | } | |
65 | ||
66 | /* FUNC4 should set flag1. | |
67 | */ | |
68 | ||
69 | void | |
70 | func4 () | |
71 | { | |
72 | scm_begin_frame (0); | |
73 | flag1 = 0; | |
c05d0e8f | 74 | scm_on_unwind (set_flag, &flag1, SCM_F_WIND_EXPLICITLY); |
3c8fb18e MV |
75 | scm_misc_error ("func4", "gratuitous error", SCM_EOL); |
76 | scm_end_frame (); | |
77 | } | |
78 | ||
79 | SCM | |
80 | check_flag1_body (void *data) | |
81 | { | |
82 | void (*f)(void) = (void (*)(void))data; | |
83 | f (); | |
84 | return SCM_UNSPECIFIED; | |
85 | } | |
86 | ||
87 | SCM | |
88 | return_tag (void *data, SCM tag, SCM args) | |
89 | { | |
90 | return tag; | |
91 | } | |
92 | ||
93 | void | |
94 | check_flag1 (const char *tag, void (*func)(void), int val) | |
95 | { | |
96 | scm_internal_catch (SCM_BOOL_T, | |
97 | check_flag1_body, func, | |
98 | return_tag, NULL); | |
99 | if (flag1 != val) | |
100 | { | |
101 | printf ("%s failed\n", tag); | |
102 | exit (1); | |
103 | } | |
104 | } | |
105 | ||
106 | SCM | |
107 | check_cont_body (void *data) | |
108 | { | |
109 | scm_t_frame_flags flags = (data? SCM_F_FRAME_REWINDABLE : 0); | |
110 | int first; | |
111 | SCM val; | |
112 | ||
113 | scm_begin_frame (flags); | |
114 | ||
115 | val = scm_make_continuation (&first); | |
116 | scm_end_frame (); | |
117 | return val; | |
118 | } | |
119 | ||
120 | void | |
121 | check_cont (int rewindable) | |
122 | { | |
123 | SCM res; | |
124 | ||
125 | res = scm_internal_catch (SCM_BOOL_T, | |
126 | check_cont_body, (void *)rewindable, | |
127 | return_tag, NULL); | |
128 | ||
129 | /* RES is now either the created continuation, the value passed to | |
130 | the continuation, or a catch-tag, such as 'misc-error. | |
131 | */ | |
132 | ||
133 | if (SCM_NFALSEP (scm_procedure_p (res))) | |
134 | { | |
135 | /* a continuation, invoke it */ | |
136 | scm_call_1 (res, SCM_BOOL_F); | |
137 | } | |
138 | else if (SCM_FALSEP (res)) | |
139 | { | |
140 | /* the result of invoking the continuation, frame must be | |
141 | rewindable */ | |
142 | if (rewindable) | |
143 | return; | |
144 | printf ("continuation not blocked\n"); | |
145 | exit (1); | |
146 | } | |
147 | else | |
148 | { | |
149 | /* the catch tag, frame must not have been rewindable. */ | |
150 | if (!rewindable) | |
151 | return; | |
152 | printf ("continuation didn't work\n"); | |
153 | exit (1); | |
154 | } | |
155 | } | |
c05d0e8f MV |
156 | |
157 | void | |
158 | close_port (SCM port) | |
159 | { | |
160 | scm_close_port (port); | |
161 | } | |
162 | ||
163 | void | |
164 | delete_file (void *data) | |
165 | { | |
166 | unlink ((char *)data); | |
167 | } | |
168 | ||
169 | void | |
170 | check_ports () | |
171 | { | |
172 | char filename[] = "/tmp/check-ports.XXXXXX"; | |
173 | ||
174 | if (mktemp (filename) == NULL) | |
175 | exit (1); | |
176 | ||
177 | scm_begin_frame (0); | |
178 | { | |
179 | SCM port = scm_open_file (scm_str2string (filename), | |
180 | scm_str2string ("w")); | |
181 | scm_on_unwind_with_scm (close_port, port, SCM_F_WIND_EXPLICITLY); | |
182 | ||
183 | scm_with_current_output_port (port); | |
184 | scm_write (scm_version (), SCM_UNDEFINED); | |
185 | } | |
186 | scm_end_frame (); | |
187 | ||
188 | scm_begin_frame (0); | |
189 | { | |
190 | SCM port = scm_open_file (scm_str2string (filename), | |
191 | scm_str2string ("r")); | |
192 | SCM res; | |
193 | scm_on_unwind_with_scm (close_port, port, SCM_F_WIND_EXPLICITLY); | |
194 | scm_on_unwind (delete_file, filename, SCM_F_WIND_EXPLICITLY); | |
195 | ||
196 | scm_with_current_input_port (port); | |
197 | res = scm_read (SCM_UNDEFINED); | |
198 | if (SCM_FALSEP (scm_equal_p (res, scm_version ()))) | |
199 | { | |
200 | printf ("ports didn't work\n"); | |
201 | exit (1); | |
202 | } | |
203 | } | |
204 | scm_end_frame (); | |
205 | } | |
3c8fb18e MV |
206 | |
207 | static void | |
208 | inner_main (void *data, int argc, char **argv) | |
209 | { | |
210 | check_flag1 ("func1", func1, 0); | |
211 | check_flag1 ("func2", func2, 1); | |
212 | check_flag1 ("func3", func3, 1); | |
213 | check_flag1 ("func4", func4, 1); | |
214 | ||
215 | check_cont (0); | |
216 | check_cont (1); | |
217 | ||
c05d0e8f MV |
218 | check_ports (); |
219 | ||
3c8fb18e MV |
220 | exit (0); |
221 | } | |
222 | ||
223 | int | |
224 | main (int argc, char **argv) | |
225 | { | |
226 | scm_boot_guile (argc, argv, inner_main, 0); | |
227 | return 0; | |
228 | } |