File: neo_err.h

package info (click to toggle)
clearsilver 0.10.5-3
  • links: PTS
  • area: main
  • in suites: buster
  • size: 3,304 kB
  • ctags: 3,158
  • sloc: ansic: 24,586; python: 4,233; sh: 2,502; cs: 1,429; ruby: 819; java: 735; makefile: 593; perl: 120; lisp: 34; sql: 21
file content (226 lines) | stat: -rw-r--r-- 7,982 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
 * Copyright 2001-2004 Brandon Long
 * All Rights Reserved.
 *
 * ClearSilver Templating System
 *
 * This code is made available under the terms of the ClearSilver License.
 * http://www.clearsilver.net/license.hdf
 *
 */

#ifndef __NEO_ERR_H_
#define __NEO_ERR_H_ 1

#include "util/neo_misc.h"

/* For compilers (well, cpp actually) which don't define __PRETTY_FUNCTION__ */
#ifndef __GNUC__
#define __PRETTY_FUNCTION__ "unknown_function"
#endif

__BEGIN_DECLS

/* For 64 bit systems which don't like mixing ints and pointers, we have the
 * _INT version for doing that comparison */
#define STATUS_OK ((NEOERR *)0)
#define STATUS_OK_INT 0
#define INTERNAL_ERR ((NEOERR *)1)
#define INTERNAL_ERR_INT 1

/* NEOERR flags */
#define NE_IN_USE (1<<0)

typedef int NERR_TYPE;

/* Predefined Error Types - These are all registered in nerr_init */
extern NERR_TYPE NERR_PASS;
extern NERR_TYPE NERR_ASSERT;
extern NERR_TYPE NERR_NOT_FOUND;
extern NERR_TYPE NERR_DUPLICATE;
extern NERR_TYPE NERR_NOMEM;
extern NERR_TYPE NERR_PARSE;
extern NERR_TYPE NERR_OUTOFRANGE;
extern NERR_TYPE NERR_SYSTEM;
extern NERR_TYPE NERR_IO;
extern NERR_TYPE NERR_LOCK;
extern NERR_TYPE NERR_DB;
extern NERR_TYPE NERR_EXISTS;

typedef struct _neo_err 
{
  int error;
  int err_stack;
  int flags;
  char desc[256];
  const char *file;
  const char *func;
  int lineno;
  /* internal use only */
  struct _neo_err *next;
} NEOERR;

/* Technically, we could do this in configure and detect what their compiler
 * can handle, but for now... */
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define USE_C99_VARARG_MACROS 1
#elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 4) || defined (S_SPLINT_S)
#define USE_GNUC_VARARG_MACROS 1
#else
#error The compiler is missing support for variable-argument macros.
#endif


/*
 * function: nerr_raise
 * description: Use this method to create an error "exception" for
 *              return up the call chain
 * arguments: using the macro, the function name, file, and lineno are
 *            automagically recorded for you.  You just provide the
 *            error (from those listed above) and the printf-style
 *            reason.  THIS IS A PRINTF STYLE FUNCTION, DO NOT PASS
 *            UNKNOWN STRING DATA AS THE FORMAT STRING.
 * returns: a pointer to a NEOERR, or INTERNAL_ERR if allocation of
 *          NEOERR fails
 */
#if defined(USE_C99_VARARG_MACROS)
#define nerr_raise(e,f,...) \
   nerr_raisef(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f, ##__VA_ARGS__)
#elif defined(USE_GNUC_VARARG_MACROS)
#define nerr_raise(e,f,a...) \
   nerr_raisef(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f,##a)
#endif

NEOERR *nerr_raisef (const char *func, const char *file, int lineno,
                     NERR_TYPE error, const char *fmt, ...)
                     ATTRIBUTE_PRINTF(5,6);
  


#if defined(USE_C99_VARARG_MACROS)
#define nerr_raise_errno(e,f,...) \
   nerr_raise_errnof(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f, ##__VA_ARGS__)
#elif defined(USE_GNUC_VARARG_MACROS)
#define nerr_raise_errno(e,f,a...) \
   nerr_raise_errnof(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f,##a)
#endif

NEOERR *nerr_raise_errnof (const char *func, const char *file, int lineno,
                           int error, const char *fmt, ...)
                           ATTRIBUTE_PRINTF(5,6);

/* function: nerr_pass
 * description: this function is used to pass an error up a level in the
 *              call chain (ie, if the error isn't handled at the
 *              current level).  This allows us to track the traceback
 *              of the error.
 * arguments: with the macro, the function name, file and lineno are
 *            automagically recorded.  Just pass the error.
 * returns: a pointer to an error
 */
#define nerr_pass(e) \
   nerr_passf(__PRETTY_FUNCTION__,__FILE__,__LINE__,e)

NEOERR *nerr_passf (const char *func, const char *file, int lineno,
                    NEOERR *err);

/* function: nerr_pass_ctx
 * description: this function is used to pass an error up a level in the
 *              call chain (ie, if the error isn't handled at the
 *              current level).  This allows us to track the traceback
 *              of the error.
 *              This version includes context information about lower
 *              errors
 * arguments: with the macro, the function name, file and lineno are
 *            automagically recorded.  Just pass the error and
 *            a printf format string giving more information about where
 *            the error is occuring.
 * returns: a pointer to an error
 */
#if defined(USE_C99_VARARG_MACROS)
#define nerr_pass_ctx(e,f,...) \
   nerr_pass_ctxf(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f,__VA_ARGS__)
#elif defined(USE_GNUC_VARARG_MACROS)
#define nerr_pass_ctx(e,f,a...) \
   nerr_pass_ctxf(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f,##a)
#endif

NEOERR *nerr_pass_ctxf (const char *func, const char *file, int lineno,
                        NEOERR *err, const char *fmt, ...)
                        ATTRIBUTE_PRINTF(5,6);

/* function: nerr_log_error
 * description: currently, this prints out the error to stderr, and
 *             free's the error chain
 */
void nerr_log_error (NEOERR *err);

#include "util/neo_str.h"
/* function: nerr_error_string
 * description: returns the string associated with an error (the bottom
 *              level of the error chain)
 * arguments: err - error
 *            str - string to which the data is appended
 * returns: None - errors appending to the string are ignored
 */
void nerr_error_string (NEOERR *err, STRING *str);

/* function: nerr_error_traceback
 * description: returns the full traceback of the error chain
 * arguments: err - error
 *            str - string to which the data is appended
 * returns: None - errors appending to the string are ignored
 */
void nerr_error_traceback (NEOERR *err, STRING *str);

/* function: nerr_ignore
 * description: you should only call this if you actually handle the
 *              error (should I rename it?).  Free's the error chain.
 */
void nerr_ignore (NEOERR **err);

/* function: nerr_register
 * description: register an error type.  This will assign a numeric value
 *              to the type, and keep track of the "pretty name" for it.
 * arguments: err - pointer to a NERR_TYPE
 *            name - pretty name for the error type
 * returns: NERR_NOMEM on no memory
 */
NEOERR *nerr_register (NERR_TYPE *err, const char *name);

/* function: nerr_init
 * description: initialize the NEOERR system.  Can be called more than once.
 *              Is not thread safe.  This registers all of the built in
 *              error types as defined at the top of this file.  If you don't
 *              call this, all exceptions will be returned as UnknownError.
 * arguments: None
 * returns: possibly NERR_NOMEM, but somewhat unlikely.  Possibly an
 *          UnknownError if NERR_NOMEM hasn't been registered yet.
 */
NEOERR *nerr_init (void);

/* function: nerr_match
 * description: nerr_match is used to walk the NEOERR chain and match
 *              the error against a specific error type.  In exception
 *              parlance, this would be the equivalent of "catch".
 *              Typically, you can just compare a NEOERR against STATUS_OK
 *              or just test for true if you are checking for any error.
 * arguments: err - the NEOERR that has an error.
 *            type - the NEOERR type, as registered with nerr_register
 * returns: true on match
 */
int nerr_match (NEOERR *err, NERR_TYPE type);

/* function: nerr_handle
 * description: nerr_handle is a convenience function.  It is the equivalent
 *              of nerr_match, but it will also deallocate the error chain
 *              on a match.
 * arguments: err - pointer to a pointer NEOERR
 *            type - the NEOERR type, as registered with nerr_register
 * returns: true on match
 */
int nerr_handle (NEOERR **err, NERR_TYPE type);

__END_DECLS

#endif /* __NEO_ERR_H_ */