err.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /**************************************************************************
  2. **
  3. ** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved.
  4. **
  5. ** Meschach Library
  6. **
  7. ** This Meschach Library is provided "as is" without any express
  8. ** or implied warranty of any kind with respect to this software.
  9. ** In particular the authors shall not be liable for any direct,
  10. ** indirect, special, incidental or consequential damages arising
  11. ** in any way from use of the software.
  12. **
  13. ** Everyone is granted permission to copy, modify and redistribute this
  14. ** Meschach Library, provided:
  15. ** 1. All copies contain this copyright notice.
  16. ** 2. All modified copies shall carry a notice stating who
  17. ** made the last modification and the date of such modification.
  18. ** 3. No charge is made for this software or works derived from it.
  19. ** This clause shall not be construed as constraining other software
  20. ** distributed on the same medium as this software, nor is a
  21. ** distribution fee considered a charge.
  22. **
  23. ***************************************************************************/
  24. /*
  25. File with basic error-handling operations
  26. */
  27. static char rcsid[] = "$Id: err.c,v 1.6 1995/01/30 14:49:14 des Exp $";
  28. #include <stdio.h>
  29. #include <setjmp.h>
  30. #include <ctype.h>
  31. #include "err.h"
  32. #ifdef SYSV
  33. /* AT&T System V */
  34. #include <sys/signal.h>
  35. #else
  36. /* something else -- assume BSD or ANSI C */
  37. #include <signal.h>
  38. #endif
  39. #define FALSE 0
  40. #define TRUE 1
  41. #define EF_EXIT 0
  42. #define EF_ABORT 1
  43. #define EF_JUMP 2
  44. #define EF_SILENT 3
  45. /* The only error caught in this file! */
  46. #define E_SIGNAL 16
  47. static char *err_mesg[] =
  48. { "unknown error", /* 0 */
  49. "sizes of objects don't match", /* 1 */
  50. "index out of bounds", /* 2 */
  51. "can't allocate memory", /* 3 */
  52. "singular matrix", /* 4 */
  53. "matrix not positive definite", /* 5 */
  54. "incorrect format input", /* 6 */
  55. "bad input file/device", /* 7 */
  56. "NULL objects passed", /* 8 */
  57. "matrix not square", /* 9 */
  58. "object out of range", /* 10 */
  59. "can't do operation in situ for non-square matrix", /* 11 */
  60. "can't do operation in situ", /* 12 */
  61. "excessive number of iterations", /* 13 */
  62. "convergence criterion failed", /* 14 */
  63. "bad starting value", /* 15 */
  64. "floating exception", /* 16 */
  65. "internal inconsistency (data structure)",/* 17 */
  66. "unexpected end-of-file", /* 18 */
  67. "shared vectors (cannot release them)", /* 19 */
  68. "negative argument", /* 20 */
  69. "cannot overwrite object", /* 21 */
  70. "breakdown in iterative method" /* 22 */
  71. };
  72. #define MAXERR (sizeof(err_mesg)/sizeof(char *))
  73. static char *warn_mesg[] = {
  74. "unknown warning", /* 0 */
  75. "wrong type number (use macro TYPE_*)", /* 1 */
  76. "no corresponding mem_stat_mark", /* 2 */
  77. "computed norm of a residual is less than 0", /* 3 */
  78. "resizing a shared vector" /* 4 */
  79. };
  80. #define MAXWARN (sizeof(warn_mesg)/sizeof(char *))
  81. #define MAX_ERRS 100
  82. jmp_buf restart;
  83. /* array of pointers to lists of errors */
  84. typedef struct {
  85. char **listp; /* pointer to a list of errors */
  86. unsigned len; /* length of the list */
  87. unsigned warn; /* =FALSE - errors, =TRUE - warnings */
  88. } Err_list;
  89. static Err_list err_list[ERR_LIST_MAX_LEN] = {
  90. {err_mesg,MAXERR,FALSE}, /* basic errors list */
  91. {warn_mesg,MAXWARN,TRUE} /* basic warnings list */
  92. };
  93. static int err_list_end = 2; /* number of elements in err_list */
  94. /* attach a new list of errors pointed by err_ptr
  95. or change a previous one;
  96. list_len is the number of elements in the list;
  97. list_num is the list number;
  98. warn == FALSE - errors (stop the program),
  99. warn == TRUE - warnings (continue the program);
  100. Note: lists numbered 0 and 1 are attached automatically,
  101. you do not need to do it
  102. */
  103. #ifndef ANSI_C
  104. int err_list_attach(list_num, list_len,err_ptr,warn)
  105. int list_num, list_len, warn;
  106. char **err_ptr;
  107. #else
  108. int err_list_attach(int list_num, int list_len, char **err_ptr, int warn)
  109. #endif
  110. {
  111. if (list_num < 0 || list_len <= 0 ||
  112. err_ptr == (char **)NULL)
  113. return -1;
  114. if (list_num >= ERR_LIST_MAX_LEN) {
  115. fprintf(stderr,"\n file \"%s\": %s %s\n",
  116. "err.c","increase the value of ERR_LIST_MAX_LEN",
  117. "in matrix.h and zmatdef.h");
  118. if ( ! isatty(fileno(stdout)) )
  119. fprintf(stderr,"\n file \"%s\": %s %s\n",
  120. "err.c","increase the value of ERR_LIST_MAX_LEN",
  121. "in matrix.h and zmatdef.h");
  122. printf("Exiting program\n");
  123. exit(0);
  124. }
  125. if (err_list[list_num].listp != (char **)NULL &&
  126. err_list[list_num].listp != err_ptr)
  127. free((char *)err_list[list_num].listp);
  128. err_list[list_num].listp = err_ptr;
  129. err_list[list_num].len = list_len;
  130. err_list[list_num].warn = warn;
  131. err_list_end = list_num+1;
  132. return list_num;
  133. }
  134. /* release the error list numbered list_num */
  135. #ifndef ANSI_C
  136. int err_list_free(list_num)
  137. int list_num;
  138. #else
  139. int err_list_free(int list_num)
  140. #endif
  141. {
  142. if (list_num < 0 || list_num >= err_list_end) return -1;
  143. if (err_list[list_num].listp != (char **)NULL) {
  144. err_list[list_num].listp = (char **)NULL;
  145. err_list[list_num].len = 0;
  146. err_list[list_num].warn = 0;
  147. }
  148. return 0;
  149. }
  150. /* check if list_num is attached;
  151. return FALSE if not;
  152. return TRUE if yes
  153. */
  154. #ifndef ANSI_C
  155. int err_is_list_attached(list_num)
  156. int list_num;
  157. #else
  158. int err_is_list_attached(int list_num)
  159. #endif
  160. {
  161. if (list_num < 0 || list_num >= err_list_end)
  162. return FALSE;
  163. if (err_list[list_num].listp != (char **)NULL)
  164. return TRUE;
  165. return FALSE;
  166. }
  167. /* other local variables */
  168. static int err_flag = EF_EXIT, num_errs = 0, cnt_errs = 1;
  169. /* set_err_flag -- sets err_flag -- returns old err_flag */
  170. #ifndef ANSI_C
  171. int set_err_flag(flag)
  172. int flag;
  173. #else
  174. int set_err_flag(int flag)
  175. #endif
  176. {
  177. int tmp;
  178. tmp = err_flag;
  179. err_flag = flag;
  180. return tmp;
  181. }
  182. /* count_errs -- sets cnt_errs (TRUE/FALSE) & returns old value */
  183. #ifndef ANSI_C
  184. int count_errs(flag)
  185. int flag;
  186. #else
  187. int count_errs(int flag)
  188. #endif
  189. {
  190. int tmp;
  191. tmp = cnt_errs;
  192. cnt_errs = flag;
  193. return tmp;
  194. }
  195. /* ev_err -- reports error (err_num) in file "file" at line "line_num" and
  196. returns to user error handler;
  197. list_num is an error list number (0 is the basic list
  198. pointed by err_mesg, 1 is the basic list of warnings)
  199. */
  200. #ifndef ANSI_C
  201. int ev_err(file,err_num,line_num,fn_name,list_num)
  202. char *file, *fn_name;
  203. int err_num, line_num,list_num;
  204. #else
  205. int ev_err(const char *file, int err_num, int line_num,
  206. const char *fn_name, int list_num)
  207. #endif
  208. {
  209. int num;
  210. if ( err_num < 0 ) err_num = 0;
  211. if (list_num < 0 || list_num >= err_list_end ||
  212. err_list[list_num].listp == (char **)NULL) {
  213. fprintf(stderr,
  214. "\n Not (properly) attached list of errors: list_num = %d\n",
  215. list_num);
  216. fprintf(stderr," Call \"err_list_attach\" in your program\n");
  217. if ( ! isatty(fileno(stdout)) ) {
  218. fprintf(stderr,
  219. "\n Not (properly) attached list of errors: list_num = %d\n",
  220. list_num);
  221. fprintf(stderr," Call \"err_list_attach\" in your program\n");
  222. }
  223. printf("\nExiting program\n");
  224. exit(0);
  225. }
  226. num = err_num;
  227. if ( num >= err_list[list_num].len ) num = 0;
  228. if ( cnt_errs && ++num_errs >= MAX_ERRS ) /* too many errors */
  229. {
  230. fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n",
  231. file,line_num,err_list[list_num].listp[num],
  232. isascii(*fn_name) ? fn_name : "???");
  233. if ( ! isatty(fileno(stdout)) )
  234. fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n",
  235. file,line_num,err_list[list_num].listp[num],
  236. isascii(*fn_name) ? fn_name : "???");
  237. printf("Sorry, too many errors: %d\n",num_errs);
  238. printf("Exiting program\n");
  239. exit(0);
  240. }
  241. if ( err_list[list_num].warn )
  242. switch ( err_flag )
  243. {
  244. case EF_SILENT: break;
  245. default:
  246. fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n\n",
  247. file,line_num,err_list[list_num].listp[num],
  248. isascii(*fn_name) ? fn_name : "???");
  249. if ( ! isatty(fileno(stdout)) )
  250. fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n\n",
  251. file,line_num,err_list[list_num].listp[num],
  252. isascii(*fn_name) ? fn_name : "???");
  253. break;
  254. }
  255. else
  256. switch ( err_flag )
  257. {
  258. case EF_SILENT:
  259. longjmp(restart,(err_num==0)? -1 : err_num);
  260. break;
  261. case EF_ABORT:
  262. fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n",
  263. file,line_num,err_list[list_num].listp[num],
  264. isascii(*fn_name) ? fn_name : "???");
  265. if ( ! isatty(fileno(stdout)) )
  266. fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n",
  267. file,line_num,err_list[list_num].listp[num],
  268. isascii(*fn_name) ? fn_name : "???");
  269. abort();
  270. break;
  271. case EF_JUMP:
  272. fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n",
  273. file,line_num,err_list[list_num].listp[num],
  274. isascii(*fn_name) ? fn_name : "???");
  275. if ( ! isatty(fileno(stdout)) )
  276. fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n",
  277. file,line_num,err_list[list_num].listp[num],
  278. isascii(*fn_name) ? fn_name : "???");
  279. longjmp(restart,(err_num==0)? -1 : err_num);
  280. break;
  281. default:
  282. fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n\n",
  283. file,line_num,err_list[list_num].listp[num],
  284. isascii(*fn_name) ? fn_name : "???");
  285. if ( ! isatty(fileno(stdout)) )
  286. fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n\n",
  287. file,line_num,err_list[list_num].listp[num],
  288. isascii(*fn_name) ? fn_name : "???");
  289. break;
  290. }
  291. /* ensure exit if fall through */
  292. if ( ! err_list[list_num].warn ) exit(0);
  293. return 0;
  294. }
  295. /* float_error -- catches floating arithmetic signals */
  296. #ifndef ANSI_C
  297. static void float_error(num)
  298. int num;
  299. #else
  300. static void float_error(int num)
  301. #endif
  302. {
  303. signal(SIGFPE,float_error);
  304. /* fprintf(stderr,"SIGFPE: signal #%d\n",num); */
  305. /* fprintf(stderr,"errno = %d\n",errno); */
  306. ev_err("???.c",E_SIGNAL,0,"???",0);
  307. }
  308. /* catch_signal -- sets up float_error() to catch SIGFPE's */
  309. void catch_FPE()
  310. {
  311. signal(SIGFPE,float_error);
  312. }