GOOPS cosmetics
[bpt/guile.git] / libguile / error.c
CommitLineData
fda17c20
MW
1/* Copyright (C) 1995-1998, 2000, 2001, 2004, 2006, 2010, 2012-2014
2 * 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;
fda17c20
MW
124 int errnum = scm_to_int (err); /* Must be done outside of the
125 critical section below, to avoid a
126 deadlock on errors. */
661ae7ab
MV
127 scm_dynwind_begin (0);
128 scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex);
4af3c6f1 129
fda17c20 130 ret = scm_from_locale_string (strerror (errnum));
4af3c6f1 131
661ae7ab 132 scm_dynwind_end ();
4af3c6f1 133 return ret;
efb997f5 134}
1bbd0b84 135#undef FUNC_NAME
efb997f5 136
a7f54aed 137SCM_GLOBAL_SYMBOL (scm_system_error_key, "system-error");
52859adf 138void
1bbd0b84 139scm_syserror (const char *subr)
52859adf 140{
09b204d3 141 SCM err = scm_from_int (errno);
41e82649
AW
142
143 /* It could be that we're getting here because the syscall was
144 interrupted by a signal. In that case a signal handler might have
145 been queued to run. The signal handler probably throws an
146 exception.
147
148 If we don't try to run the signal handler now, it will run later,
149 which would result in two exceptions being thrown: this syserror,
150 and then at some later time the exception thrown by the async
151 signal handler.
152
153 The problem is that we don't know if handling the signal caused an
154 async to be queued. By this time scmsigs.c:take_signal will have
155 written a byte on the fd, but we don't know if the signal-handling
156 thread has read it off and queued an async.
157
158 Ideally we need some API like scm_i_ensure_signals_delivered() to
159 catch up signal delivery. Barring that, we just cross our digits
160 and pray; it could be that we handle the signal in time, and just
161 throw once, or it could be that we miss the deadline and throw
162 twice.
163 */
164#ifdef EINTR
165 if (scm_to_int (err) == EINTR)
166 SCM_ASYNC_TICK;
167#endif
168
01f61221 169 scm_error (scm_system_error_key,
52859adf 170 subr,
70d63753 171 "~A",
4af3c6f1
KR
172 scm_cons (scm_strerror (err), SCM_EOL),
173 scm_cons (err, SCM_EOL));
52859adf
GH
174}
175
176void
1bbd0b84 177scm_syserror_msg (const char *subr, const char *message, SCM args, int eno)
52859adf 178{
41e82649
AW
179 /* See above note about the EINTR signal handling race. */
180#ifdef EINTR
181 if (eno == EINTR)
182 SCM_ASYNC_TICK;
183#endif
01f61221 184 scm_error (scm_system_error_key,
52859adf
GH
185 subr,
186 message,
187 args,
7888309b 188 scm_cons (scm_from_int (eno), SCM_EOL));
52859adf
GH
189}
190
a7f54aed 191SCM_GLOBAL_SYMBOL (scm_num_overflow_key, "numerical-overflow");
52859adf 192void
1bbd0b84 193scm_num_overflow (const char *subr)
52859adf 194{
01f61221 195 scm_error (scm_num_overflow_key,
52859adf
GH
196 subr,
197 "Numerical overflow",
198 SCM_BOOL_F,
199 SCM_BOOL_F);
200}
201
a7f54aed 202SCM_GLOBAL_SYMBOL (scm_out_of_range_key, "out-of-range");
52859adf 203void
1bbd0b84 204scm_out_of_range (const char *subr, SCM bad_value)
52859adf 205{
01f61221 206 scm_error (scm_out_of_range_key,
52859adf 207 subr,
cdd8c091 208 "Value out of range: ~S",
1afff620 209 scm_list_1 (bad_value),
cdd8c091 210 scm_list_1 (bad_value));
52859adf 211}
f5bf2977 212
1e76143f
GB
213void
214scm_out_of_range_pos (const char *subr, SCM bad_value, SCM pos)
215{
216 scm_error (scm_out_of_range_key,
217 subr,
cdd8c091 218 "Argument ~A out of range: ~S",
34d19ef6 219 scm_list_2 (pos, bad_value),
cdd8c091 220 scm_list_1 (bad_value));
1e76143f
GB
221}
222
223
a7f54aed 224SCM_GLOBAL_SYMBOL (scm_args_number_key, "wrong-number-of-args");
0f2d19dd 225void
1bbd0b84 226scm_wrong_num_args (SCM proc)
f5bf2977 227{
01f61221 228 scm_error (scm_args_number_key,
f5bf2977 229 NULL,
70d63753 230 "Wrong number of arguments to ~A",
1afff620 231 scm_list_1 (proc),
f5bf2977
GH
232 SCM_BOOL_F);
233}
234
9f40cd87
DH
235
236void
237scm_error_num_args_subr (const char *subr)
238{
239 scm_error (scm_args_number_key,
240 NULL,
241 "Wrong number of arguments to ~A",
468e87a7 242 scm_list_1 (scm_from_locale_string (subr)),
9f40cd87
DH
243 SCM_BOOL_F);
244}
245
246
a7f54aed 247SCM_GLOBAL_SYMBOL (scm_arg_type_key, "wrong-type-arg");
f5bf2977 248void
1bbd0b84 249scm_wrong_type_arg (const char *subr, int pos, SCM bad_value)
f5bf2977 250{
01f61221 251 scm_error (scm_arg_type_key,
f5bf2977 252 subr,
83e1ab6d 253 (pos == 0) ? "Wrong type: ~S"
70d63753 254 : "Wrong type argument in position ~A: ~S",
1afff620 255 (pos == 0) ? scm_list_1 (bad_value)
e11e83f3 256 : scm_list_2 (scm_from_int (pos), bad_value),
cdd8c091 257 scm_list_1 (bad_value));
f5bf2977
GH
258}
259
0193377d
MG
260void
261scm_i_wrong_type_arg_symbol (SCM symbol, int pos, SCM bad_value)
262{
263 scm_error_scm (scm_arg_type_key,
264 scm_symbol_to_string (symbol),
265 (pos == 0) ? scm_from_locale_string ("Wrong type: ~S")
266 : scm_from_locale_string ("Wrong type argument in position ~A: ~S"),
267 (pos == 0) ? scm_list_1 (bad_value)
268 : scm_list_2 (scm_from_int (pos), bad_value),
269 scm_list_1 (bad_value));
270 scm_remember_upto_here_2 (symbol, bad_value);
271}
272
b6791b2e
GB
273void
274scm_wrong_type_arg_msg (const char *subr, int pos, SCM bad_value, const char *szMessage)
275{
468e87a7 276 SCM msg = scm_from_locale_string (szMessage);
cdd8c091
MV
277 if (pos == 0)
278 {
279 scm_error (scm_arg_type_key,
280 subr, "Wrong type (expecting ~A): ~S",
281 scm_list_2 (msg, bad_value),
282 scm_list_1 (bad_value));
283 }
284 else
285 {
286 scm_error (scm_arg_type_key,
287 subr,
288 "Wrong type argument in position ~A (expecting ~A): ~S",
289 scm_list_3 (scm_from_int (pos), msg, bad_value),
290 scm_list_1 (bad_value));
291 }
b6791b2e
GB
292}
293
294
a7f54aed 295SCM_GLOBAL_SYMBOL (scm_misc_error_key, "misc-error");
523f5266 296void
1bbd0b84 297scm_misc_error (const char *subr, const char *message, SCM args)
523f5266
GH
298{
299 scm_error (scm_misc_error_key, subr, message, args, SCM_BOOL_F);
300}
301
0f2d19dd
JB
302void
303scm_init_error ()
0f2d19dd 304{
648da032 305#include "libguile/cpp-E.c"
a0599745 306#include "libguile/error.x"
0f2d19dd
JB
307}
308
89e00824
ML
309
310/*
311 Local Variables:
312 c-file-style: "gnu"
313 End:
314*/