degenerate let forms
[bpt/guile.git] / libguile / error.c
CommitLineData
bb796c46 1/* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2004, 2006, 2010,
c2247b78 2 * 2012, 2013, 2014 Free Software Foundation, Inc.
bb796c46 3 *
73be1d9e 4 * This library is free software; you can redistribute it and/or
53befeb7
NJ
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
0f2d19dd 8 *
53befeb7
NJ
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
0f2d19dd 13 *
73be1d9e
MV
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
53befeb7
NJ
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
73be1d9e 18 */
1bbd0b84 19
1bbd0b84 20
0f2d19dd
JB
21\f
22
dbb605f5 23#ifdef HAVE_CONFIG_H
4600886f
RB
24# include <config.h>
25#endif
26
93003b16 27#include <stdlib.h>
0f2d19dd 28#include <stdio.h>
e6e2e95a 29#include <errno.h>
bd9e24b3 30
a0599745 31#include "libguile/_scm.h"
4af3c6f1 32#include "libguile/dynwind.h"
a0599745
MD
33#include "libguile/pairs.h"
34#include "libguile/strings.h"
35#include "libguile/throw.h"
20e6290e 36
a0599745
MD
37#include "libguile/validate.h"
38#include "libguile/error.h"
0f2d19dd 39
bd9e24b3
GH
40#ifdef HAVE_STRING_H
41#include <string.h>
42#endif
95b88819 43#include <unistd.h>
7beabedb
MG
44
45/* For Windows... */
46#ifdef HAVE_IO_H
47#include <io.h>
48#endif
0f2d19dd
JB
49\f
50
0f2d19dd
JB
51/* {Errors and Exceptional Conditions}
52 */
53
0f2d19dd 54
24d1f171 55/* Scheme interface to scm_error_scm. */
7cb1d4d3 56void
1bbd0b84 57scm_error (SCM key, const char *subr, const char *message, SCM args, SCM rest)
7cb1d4d3 58{
24d1f171
MV
59 scm_error_scm
60 (key,
61 (subr == NULL) ? SCM_BOOL_F : scm_from_locale_string (subr),
62 (message == NULL) ? SCM_BOOL_F : scm_from_locale_string (message),
63 args, rest);
7cb1d4d3 64}
0f2d19dd 65
24d1f171 66/* All errors should pass through here. */
3b3b36dd 67SCM_DEFINE (scm_error_scm, "scm-error", 5, 0, 0,
1e6808ea
MG
68 (SCM key, SCM subr, SCM message, SCM args, SCM data),
69 "Raise an error with key @var{key}. @var{subr} can be a string\n"
70 "naming the procedure associated with the error, or @code{#f}.\n"
71 "@var{message} is the error message string, possibly containing\n"
72 "@code{~S} and @code{~A} escapes. When an error is reported,\n"
73 "these are replaced by formatting the corresponding members of\n"
74 "@var{args}: @code{~A} (was @code{%s} in older versions of\n"
75 "Guile) formats using @code{display} and @code{~S} (was\n"
76 "@code{%S}) formats using @code{write}. @var{data} is a list or\n"
77 "@code{#f} depending on @var{key}: if @var{key} is\n"
78 "@code{system-error} then it should be a list containing the\n"
79 "Unix @code{errno} value; If @var{key} is @code{signal} then it\n"
cdd8c091 80 "should be a list containing the Unix signal number; If\n"
4af0d97e
LC
81 "@var{key} is @code{out-of-range}, @code{wrong-type-arg},\n"
82 "or @code{keyword-argument-error}, "
cdd8c091 83 "it is a list containing the bad value; otherwise\n"
1e6808ea 84 "it will usually be @code{#f}.")
1bbd0b84 85#define FUNC_NAME s_scm_error_scm
c37e0e55 86{
24d1f171 87 if (scm_gc_running_p)
a6d9e5ab 88 {
24d1f171
MV
89 /* The error occured during GC --- abort */
90 fprintf (stderr, "Guile: error during GC.\n"),
91 abort ();
a6d9e5ab 92 }
89958ad0 93
24d1f171
MV
94 scm_ithrow (key, scm_list_4 (subr, message, args, data), 1);
95
96 /* No return, but just in case: */
97 fprintf (stderr, "Guile scm_ithrow returned!\n");
93003b16 98 exit (EXIT_FAILURE);
c37e0e55 99}
1bbd0b84 100#undef FUNC_NAME
c37e0e55 101
4af3c6f1
KR
102/* strerror may not be thread safe, for instance in glibc (version 2.3.2) an
103 error number not among the known values results in a string like "Unknown
104 error 9999" formed in a static buffer, which will be overwritten by a
105 similar call in another thread. A test program running two threads with
106 different unknown error numbers can trip this fairly quickly.
107
108 Some systems don't do what glibc does, instead just giving a single
109 "Unknown error" for unrecognised numbers. It doesn't seem worth trying
110 to tell if that's the case, a mutex is reasonably fast, and strerror
111 isn't needed very often.
112
113 strerror_r (when available) could be used, it might be a touch faster
114 than a frame and a mutex, though there's probably not much
115 difference. */
116
a1ec6916 117SCM_DEFINE (scm_strerror, "strerror", 1, 0, 0,
1bbd0b84 118 (SCM err),
1e6808ea
MG
119 "Return the Unix error message corresponding to @var{err}, which\n"
120 "must be an integer value.")
1bbd0b84 121#define FUNC_NAME s_scm_strerror
efb997f5 122{
4af3c6f1 123 SCM ret;
661ae7ab
MV
124 scm_dynwind_begin (0);
125 scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex);
4af3c6f1 126
09b204d3 127 ret = scm_from_locale_string (strerror (scm_to_int (err)));
4af3c6f1 128
661ae7ab 129 scm_dynwind_end ();
4af3c6f1 130 return ret;
efb997f5 131}
1bbd0b84 132#undef FUNC_NAME
efb997f5 133
a7f54aed 134SCM_GLOBAL_SYMBOL (scm_system_error_key, "system-error");
52859adf 135void
1bbd0b84 136scm_syserror (const char *subr)
52859adf 137{
09b204d3 138 SCM err = scm_from_int (errno);
41e82649
AW
139
140 /* It could be that we're getting here because the syscall was
141 interrupted by a signal. In that case a signal handler might have
142 been queued to run. The signal handler probably throws an
143 exception.
144
145 If we don't try to run the signal handler now, it will run later,
146 which would result in two exceptions being thrown: this syserror,
147 and then at some later time the exception thrown by the async
148 signal handler.
149
150 The problem is that we don't know if handling the signal caused an
151 async to be queued. By this time scmsigs.c:take_signal will have
152 written a byte on the fd, but we don't know if the signal-handling
153 thread has read it off and queued an async.
154
155 Ideally we need some API like scm_i_ensure_signals_delivered() to
156 catch up signal delivery. Barring that, we just cross our digits
157 and pray; it could be that we handle the signal in time, and just
158 throw once, or it could be that we miss the deadline and throw
159 twice.
160 */
161#ifdef EINTR
162 if (scm_to_int (err) == EINTR)
163 SCM_ASYNC_TICK;
164#endif
165
01f61221 166 scm_error (scm_system_error_key,
52859adf 167 subr,
70d63753 168 "~A",
4af3c6f1
KR
169 scm_cons (scm_strerror (err), SCM_EOL),
170 scm_cons (err, SCM_EOL));
52859adf
GH
171}
172
173void
1bbd0b84 174scm_syserror_msg (const char *subr, const char *message, SCM args, int eno)
52859adf 175{
41e82649
AW
176 /* See above note about the EINTR signal handling race. */
177#ifdef EINTR
178 if (eno == EINTR)
179 SCM_ASYNC_TICK;
180#endif
01f61221 181 scm_error (scm_system_error_key,
52859adf
GH
182 subr,
183 message,
184 args,
7888309b 185 scm_cons (scm_from_int (eno), SCM_EOL));
52859adf
GH
186}
187
a7f54aed 188SCM_GLOBAL_SYMBOL (scm_num_overflow_key, "numerical-overflow");
52859adf 189void
1bbd0b84 190scm_num_overflow (const char *subr)
52859adf 191{
01f61221 192 scm_error (scm_num_overflow_key,
52859adf
GH
193 subr,
194 "Numerical overflow",
195 SCM_BOOL_F,
196 SCM_BOOL_F);
197}
198
a7f54aed 199SCM_GLOBAL_SYMBOL (scm_out_of_range_key, "out-of-range");
52859adf 200void
1bbd0b84 201scm_out_of_range (const char *subr, SCM bad_value)
52859adf 202{
01f61221 203 scm_error (scm_out_of_range_key,
52859adf 204 subr,
cdd8c091 205 "Value out of range: ~S",
1afff620 206 scm_list_1 (bad_value),
cdd8c091 207 scm_list_1 (bad_value));
52859adf 208}
f5bf2977 209
1e76143f
GB
210void
211scm_out_of_range_pos (const char *subr, SCM bad_value, SCM pos)
212{
213 scm_error (scm_out_of_range_key,
214 subr,
cdd8c091 215 "Argument ~A out of range: ~S",
34d19ef6 216 scm_list_2 (pos, bad_value),
cdd8c091 217 scm_list_1 (bad_value));
1e76143f
GB
218}
219
220
a7f54aed 221SCM_GLOBAL_SYMBOL (scm_args_number_key, "wrong-number-of-args");
0f2d19dd 222void
1bbd0b84 223scm_wrong_num_args (SCM proc)
f5bf2977 224{
01f61221 225 scm_error (scm_args_number_key,
f5bf2977 226 NULL,
70d63753 227 "Wrong number of arguments to ~A",
1afff620 228 scm_list_1 (proc),
f5bf2977
GH
229 SCM_BOOL_F);
230}
231
9f40cd87
DH
232
233void
234scm_error_num_args_subr (const char *subr)
235{
236 scm_error (scm_args_number_key,
237 NULL,
238 "Wrong number of arguments to ~A",
468e87a7 239 scm_list_1 (scm_from_locale_string (subr)),
9f40cd87
DH
240 SCM_BOOL_F);
241}
242
243
a7f54aed 244SCM_GLOBAL_SYMBOL (scm_arg_type_key, "wrong-type-arg");
f5bf2977 245void
1bbd0b84 246scm_wrong_type_arg (const char *subr, int pos, SCM bad_value)
f5bf2977 247{
01f61221 248 scm_error (scm_arg_type_key,
f5bf2977 249 subr,
83e1ab6d 250 (pos == 0) ? "Wrong type: ~S"
70d63753 251 : "Wrong type argument in position ~A: ~S",
1afff620 252 (pos == 0) ? scm_list_1 (bad_value)
e11e83f3 253 : scm_list_2 (scm_from_int (pos), bad_value),
cdd8c091 254 scm_list_1 (bad_value));
f5bf2977
GH
255}
256
0193377d
MG
257void
258scm_i_wrong_type_arg_symbol (SCM symbol, int pos, SCM bad_value)
259{
260 scm_error_scm (scm_arg_type_key,
261 scm_symbol_to_string (symbol),
262 (pos == 0) ? scm_from_locale_string ("Wrong type: ~S")
263 : scm_from_locale_string ("Wrong type argument in position ~A: ~S"),
264 (pos == 0) ? scm_list_1 (bad_value)
265 : scm_list_2 (scm_from_int (pos), bad_value),
266 scm_list_1 (bad_value));
267 scm_remember_upto_here_2 (symbol, bad_value);
268}
269
b6791b2e
GB
270void
271scm_wrong_type_arg_msg (const char *subr, int pos, SCM bad_value, const char *szMessage)
272{
468e87a7 273 SCM msg = scm_from_locale_string (szMessage);
cdd8c091
MV
274 if (pos == 0)
275 {
276 scm_error (scm_arg_type_key,
277 subr, "Wrong type (expecting ~A): ~S",
278 scm_list_2 (msg, bad_value),
279 scm_list_1 (bad_value));
280 }
281 else
282 {
283 scm_error (scm_arg_type_key,
284 subr,
285 "Wrong type argument in position ~A (expecting ~A): ~S",
286 scm_list_3 (scm_from_int (pos), msg, bad_value),
287 scm_list_1 (bad_value));
288 }
b6791b2e
GB
289}
290
291
a7f54aed 292SCM_GLOBAL_SYMBOL (scm_misc_error_key, "misc-error");
523f5266 293void
1bbd0b84 294scm_misc_error (const char *subr, const char *message, SCM args)
523f5266
GH
295{
296 scm_error (scm_misc_error_key, subr, message, args, SCM_BOOL_F);
297}
298
0f2d19dd
JB
299void
300scm_init_error ()
0f2d19dd 301{
648da032 302#include "libguile/cpp-E.c"
a0599745 303#include "libguile/error.x"
0f2d19dd
JB
304}
305
89e00824
ML
306
307/*
308 Local Variables:
309 c-file-style: "gnu"
310 End:
311*/