web: uri-encode hexadecimal percent-encoding is now uppercase
[bpt/guile.git] / libguile / error.c
CommitLineData
bb796c46 1/* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2004, 2006, 2010,
09b204d3 2 * 2012, 2013 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
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
4af3c6f1
KR
103/* strerror may not be thread safe, for instance in glibc (version 2.3.2) an
104 error number not among the known values results in a string like "Unknown
105 error 9999" formed in a static buffer, which will be overwritten by a
106 similar call in another thread. A test program running two threads with
107 different unknown error numbers can trip this fairly quickly.
108
109 Some systems don't do what glibc does, instead just giving a single
110 "Unknown error" for unrecognised numbers. It doesn't seem worth trying
111 to tell if that's the case, a mutex is reasonably fast, and strerror
112 isn't needed very often.
113
114 strerror_r (when available) could be used, it might be a touch faster
115 than a frame and a mutex, though there's probably not much
116 difference. */
117
a1ec6916 118SCM_DEFINE (scm_strerror, "strerror", 1, 0, 0,
1bbd0b84 119 (SCM err),
1e6808ea
MG
120 "Return the Unix error message corresponding to @var{err}, which\n"
121 "must be an integer value.")
1bbd0b84 122#define FUNC_NAME s_scm_strerror
efb997f5 123{
4af3c6f1 124 SCM ret;
661ae7ab
MV
125 scm_dynwind_begin (0);
126 scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex);
4af3c6f1 127
09b204d3 128 ret = scm_from_locale_string (strerror (scm_to_int (err)));
4af3c6f1 129
661ae7ab 130 scm_dynwind_end ();
4af3c6f1 131 return ret;
efb997f5 132}
1bbd0b84 133#undef FUNC_NAME
efb997f5 134
a7f54aed 135SCM_GLOBAL_SYMBOL (scm_system_error_key, "system-error");
52859adf 136void
1bbd0b84 137scm_syserror (const char *subr)
52859adf 138{
09b204d3 139 SCM err = scm_from_int (errno);
41e82649
AW
140
141 /* It could be that we're getting here because the syscall was
142 interrupted by a signal. In that case a signal handler might have
143 been queued to run. The signal handler probably throws an
144 exception.
145
146 If we don't try to run the signal handler now, it will run later,
147 which would result in two exceptions being thrown: this syserror,
148 and then at some later time the exception thrown by the async
149 signal handler.
150
151 The problem is that we don't know if handling the signal caused an
152 async to be queued. By this time scmsigs.c:take_signal will have
153 written a byte on the fd, but we don't know if the signal-handling
154 thread has read it off and queued an async.
155
156 Ideally we need some API like scm_i_ensure_signals_delivered() to
157 catch up signal delivery. Barring that, we just cross our digits
158 and pray; it could be that we handle the signal in time, and just
159 throw once, or it could be that we miss the deadline and throw
160 twice.
161 */
162#ifdef EINTR
163 if (scm_to_int (err) == EINTR)
164 SCM_ASYNC_TICK;
165#endif
166
01f61221 167 scm_error (scm_system_error_key,
52859adf 168 subr,
70d63753 169 "~A",
4af3c6f1
KR
170 scm_cons (scm_strerror (err), SCM_EOL),
171 scm_cons (err, SCM_EOL));
52859adf
GH
172}
173
174void
1bbd0b84 175scm_syserror_msg (const char *subr, const char *message, SCM args, int eno)
52859adf 176{
41e82649
AW
177 /* See above note about the EINTR signal handling race. */
178#ifdef EINTR
179 if (eno == EINTR)
180 SCM_ASYNC_TICK;
181#endif
01f61221 182 scm_error (scm_system_error_key,
52859adf
GH
183 subr,
184 message,
185 args,
7888309b 186 scm_cons (scm_from_int (eno), SCM_EOL));
52859adf
GH
187}
188
a7f54aed 189SCM_GLOBAL_SYMBOL (scm_num_overflow_key, "numerical-overflow");
52859adf 190void
1bbd0b84 191scm_num_overflow (const char *subr)
52859adf 192{
01f61221 193 scm_error (scm_num_overflow_key,
52859adf
GH
194 subr,
195 "Numerical overflow",
196 SCM_BOOL_F,
197 SCM_BOOL_F);
198}
199
a7f54aed 200SCM_GLOBAL_SYMBOL (scm_out_of_range_key, "out-of-range");
52859adf 201void
1bbd0b84 202scm_out_of_range (const char *subr, SCM bad_value)
52859adf 203{
01f61221 204 scm_error (scm_out_of_range_key,
52859adf 205 subr,
cdd8c091 206 "Value out of range: ~S",
1afff620 207 scm_list_1 (bad_value),
cdd8c091 208 scm_list_1 (bad_value));
52859adf 209}
f5bf2977 210
1e76143f
GB
211void
212scm_out_of_range_pos (const char *subr, SCM bad_value, SCM pos)
213{
214 scm_error (scm_out_of_range_key,
215 subr,
cdd8c091 216 "Argument ~A out of range: ~S",
34d19ef6 217 scm_list_2 (pos, bad_value),
cdd8c091 218 scm_list_1 (bad_value));
1e76143f
GB
219}
220
221
a7f54aed 222SCM_GLOBAL_SYMBOL (scm_args_number_key, "wrong-number-of-args");
0f2d19dd 223void
1bbd0b84 224scm_wrong_num_args (SCM proc)
f5bf2977 225{
01f61221 226 scm_error (scm_args_number_key,
f5bf2977 227 NULL,
70d63753 228 "Wrong number of arguments to ~A",
1afff620 229 scm_list_1 (proc),
f5bf2977
GH
230 SCM_BOOL_F);
231}
232
9f40cd87
DH
233
234void
235scm_error_num_args_subr (const char *subr)
236{
237 scm_error (scm_args_number_key,
238 NULL,
239 "Wrong number of arguments to ~A",
468e87a7 240 scm_list_1 (scm_from_locale_string (subr)),
9f40cd87
DH
241 SCM_BOOL_F);
242}
243
244
a7f54aed 245SCM_GLOBAL_SYMBOL (scm_arg_type_key, "wrong-type-arg");
f5bf2977 246void
1bbd0b84 247scm_wrong_type_arg (const char *subr, int pos, SCM bad_value)
f5bf2977 248{
01f61221 249 scm_error (scm_arg_type_key,
f5bf2977 250 subr,
83e1ab6d 251 (pos == 0) ? "Wrong type: ~S"
70d63753 252 : "Wrong type argument in position ~A: ~S",
1afff620 253 (pos == 0) ? scm_list_1 (bad_value)
e11e83f3 254 : scm_list_2 (scm_from_int (pos), bad_value),
cdd8c091 255 scm_list_1 (bad_value));
f5bf2977
GH
256}
257
0193377d
MG
258void
259scm_i_wrong_type_arg_symbol (SCM symbol, int pos, SCM bad_value)
260{
261 scm_error_scm (scm_arg_type_key,
262 scm_symbol_to_string (symbol),
263 (pos == 0) ? scm_from_locale_string ("Wrong type: ~S")
264 : scm_from_locale_string ("Wrong type argument in position ~A: ~S"),
265 (pos == 0) ? scm_list_1 (bad_value)
266 : scm_list_2 (scm_from_int (pos), bad_value),
267 scm_list_1 (bad_value));
268 scm_remember_upto_here_2 (symbol, bad_value);
269}
270
b6791b2e
GB
271void
272scm_wrong_type_arg_msg (const char *subr, int pos, SCM bad_value, const char *szMessage)
273{
468e87a7 274 SCM msg = scm_from_locale_string (szMessage);
cdd8c091
MV
275 if (pos == 0)
276 {
277 scm_error (scm_arg_type_key,
278 subr, "Wrong type (expecting ~A): ~S",
279 scm_list_2 (msg, bad_value),
280 scm_list_1 (bad_value));
281 }
282 else
283 {
284 scm_error (scm_arg_type_key,
285 subr,
286 "Wrong type argument in position ~A (expecting ~A): ~S",
287 scm_list_3 (scm_from_int (pos), msg, bad_value),
288 scm_list_1 (bad_value));
289 }
b6791b2e
GB
290}
291
292
a7f54aed 293SCM_GLOBAL_SYMBOL (scm_memory_alloc_key, "memory-allocation-error");
f5bf2977 294void
1bbd0b84 295scm_memory_error (const char *subr)
f5bf2977 296{
468e87a7
MV
297 fprintf (stderr, "FATAL: memory error in %s\n", subr);
298 abort ();
f5bf2977
GH
299}
300
a7f54aed 301SCM_GLOBAL_SYMBOL (scm_misc_error_key, "misc-error");
523f5266 302void
1bbd0b84 303scm_misc_error (const char *subr, const char *message, SCM args)
523f5266
GH
304{
305 scm_error (scm_misc_error_key, subr, message, args, SCM_BOOL_F);
306}
307
0f2d19dd
JB
308void
309scm_init_error ()
0f2d19dd 310{
648da032 311#include "libguile/cpp-E.c"
a0599745 312#include "libguile/error.x"
0f2d19dd
JB
313}
314
89e00824
ML
315
316/*
317 Local Variables:
318 c-file-style: "gnu"
319 End:
320*/