error.c 9.3 KB

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