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