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