2 * Copyright 2001-2004 Brandon Long
5 * ClearSilver Templating System
7 * This code is made available under the terms of the ClearSilver License.
8 * http://www.clearsilver.net/license.hdf
12 #include "cs_config.h"
27 int NERR_NOT_FOUND
= 0;
28 int NERR_DUPLICATE
= 0;
31 int NERR_OUTOFRANGE
= 0;
37 int NERR_MAX_RECURSION
= 0;
39 static ULIST
*Errors
= NULL
;
40 static int Inited
= 0;
42 /* In multi-threaded environments, we have to init thread safely */
43 static pthread_mutex_t InitLock
= PTHREAD_MUTEX_INITIALIZER
;
47 static NEOERR
*_err_alloc(void)
49 NEOERR
*err
= (NEOERR
*)calloc (1, sizeof (NEOERR
));
52 ne_warn ("INTERNAL ERROR: Unable to allocate memory for NEOERR");
58 NEOERR
*nerr_raisef (const char *func
, const char *file
, int lineno
, int error
,
65 if (err
== INTERNAL_ERR
)
69 vsnprintf (err
->desc
, sizeof(err
->desc
), fmt
, ap
);
80 NEOERR
*nerr_raise_errnof (const char *func
, const char *file
, int lineno
,
81 int error
, const char *fmt
, ...)
88 if (err
== INTERNAL_ERR
)
92 vsnprintf (err
->desc
, sizeof(err
->desc
), fmt
, ap
);
95 l
= strlen(err
->desc
);
96 snprintf (err
->desc
+ l
, sizeof(err
->desc
)-l
, ": [%d] %s", errno
,
102 err
->lineno
= lineno
;
107 NEOERR
*nerr_passf (const char *func
, const char *file
, int lineno
, NEOERR
*err
)
111 if (err
== STATUS_OK
)
115 if (nerr
== INTERNAL_ERR
)
118 nerr
->error
= NERR_PASS
;
121 nerr
->lineno
= lineno
;
127 NEOERR
*nerr_pass_ctxf (const char *func
, const char *file
, int lineno
,
128 NEOERR
*err
, const char *fmt
, ...)
133 if (err
== STATUS_OK
)
137 if (nerr
== INTERNAL_ERR
)
141 vsnprintf (nerr
->desc
, sizeof(nerr
->desc
), fmt
, ap
);
144 nerr
->error
= NERR_PASS
;
147 nerr
->lineno
= lineno
;
153 /* In the future, we'll allow someone to register an error handler */
154 void nerr_log_error (NEOERR
*err
)
160 if (err
== STATUS_OK
)
163 if (err
== INTERNAL_ERR
)
165 ne_warn ("Internal error");
170 fprintf (stderr
, "Traceback (innermost last):\n");
171 while (more
&& more
!= INTERNAL_ERR
)
175 if (err
->error
!= NERR_PASS
)
181 snprintf (buf
, sizeof (buf
), "Unknown Error");
185 r
= uListGet (Errors
, err
->error
- 1, (void **)&err_name
);
189 snprintf (buf
, sizeof (buf
), "Error %d", err
->error
);
193 fprintf (stderr
, " File \"%s\", line %d, in %s()\n%s: %s\n", err
->file
,
194 err
->lineno
, err
->func
, err_name
, err
->desc
);
198 fprintf (stderr
, " File \"%s\", line %d, in %s()\n", err
->file
,
199 err
->lineno
, err
->func
);
202 fprintf (stderr
, " %s\n", err
->desc
);
208 void nerr_error_string (NEOERR
*err
, NEOSTRING
*str
)
214 if (err
== STATUS_OK
)
217 if (err
== INTERNAL_ERR
)
219 string_append (str
, "Internal error");
224 while (more
&& more
!= INTERNAL_ERR
)
228 if (err
->error
!= NERR_PASS
)
234 snprintf (buf
, sizeof (buf
), "Unknown Error");
238 r
= uListGet (Errors
, err
->error
- 1, (void **)&err_name
);
242 snprintf (buf
, sizeof (buf
), "Error %d", err
->error
);
246 string_appendf(str
, "%s: %s", err_name
, err
->desc
);
252 NEOERR
*nerr_register (int *val
, const char *name
)
256 err
= uListAppend (Errors
, (void *) name
);
257 if (err
!= STATUS_OK
) return nerr_pass(err
);
259 *val
= uListLength(Errors
);
263 NEOERR
*nerr_init (void)
270 /* In threaded environments, we have to mutex lock to do this init, but
271 * we don't want to use a mutex every time to check that it was Inited.
272 * So, we only lock if our first test of Inited was false */
273 err
= mLock(&InitLock
);
274 if (err
!= STATUS_OK
) return nerr_pass(err
);
277 err
= uListInit (&Errors
, 10, 0);
278 if (err
!= STATUS_OK
) return nerr_pass(err
);
280 err
= nerr_register (&NERR_PASS
, "InternalPass");
281 if (err
!= STATUS_OK
) return nerr_pass(err
);
282 err
= nerr_register (&NERR_ASSERT
, "AssertError");
283 if (err
!= STATUS_OK
) return nerr_pass(err
);
284 err
= nerr_register (&NERR_NOT_FOUND
, "NotFoundError");
285 if (err
!= STATUS_OK
) return nerr_pass(err
);
286 err
= nerr_register (&NERR_DUPLICATE
, "DuplicateError");
287 if (err
!= STATUS_OK
) return nerr_pass(err
);
288 err
= nerr_register (&NERR_NOMEM
, "MemoryError");
289 if (err
!= STATUS_OK
) return nerr_pass(err
);
290 err
= nerr_register (&NERR_PARSE
, "ParseError");
291 if (err
!= STATUS_OK
) return nerr_pass(err
);
292 err
= nerr_register (&NERR_OUTOFRANGE
, "RangeError");
293 if (err
!= STATUS_OK
) return nerr_pass(err
);
294 err
= nerr_register (&NERR_SYSTEM
, "SystemError");
295 if (err
!= STATUS_OK
) return nerr_pass(err
);
296 err
= nerr_register (&NERR_IO
, "IOError");
297 if (err
!= STATUS_OK
) return nerr_pass(err
);
298 err
= nerr_register (&NERR_LOCK
, "LockError");
299 if (err
!= STATUS_OK
) return nerr_pass(err
);
300 err
= nerr_register (&NERR_DB
, "DBError");
301 if (err
!= STATUS_OK
) return nerr_pass(err
);
302 err
= nerr_register (&NERR_EXISTS
, "ExistsError");
303 if (err
!= STATUS_OK
) return nerr_pass(err
);
304 err
= nerr_register (&NERR_MAX_RECURSION
, "MaxRecursionError");
305 if (err
!= STATUS_OK
) return nerr_pass(err
);
310 err
= mUnlock(&InitLock
);
311 if (err
!= STATUS_OK
) return nerr_pass(err
);