1 /* 2 * Copyright 2001-2004 Brandon Long 3 * All Rights Reserved. 4 * 5 * ClearSilver Templating System 6 * 7 * This code is made available under the terms of the ClearSilver License. 8 * http://www.clearsilver.net/license.hdf 9 * 10 */ 11 12 #ifndef __NEO_ERR_H_ 13 #define __NEO_ERR_H_ 1 14 15 #include "util/neo_misc.h" 16 17 /* For compilers (well, cpp actually) which don't define __PRETTY_FUNCTION__ */ 18 #ifndef __GNUC__ 19 #define __PRETTY_FUNCTION__ "unknown_function" 20 #endif 21 22 __BEGIN_DECLS 23 24 /* For 64 bit systems which don't like mixing ints and pointers, we have the 25 * _INT version for doing that comparison */ 26 #define STATUS_OK ((NEOERR *)0) 27 #define STATUS_OK_INT 0 28 #define INTERNAL_ERR ((NEOERR *)1) 29 #define INTERNAL_ERR_INT 1 30 31 /* NEOERR flags */ 32 #define NE_IN_USE (1<<0) 33 34 typedef int NERR_TYPE; 35 36 /* Predefined Error Types - These are all registered in nerr_init */ 37 extern NERR_TYPE NERR_PASS; 38 extern NERR_TYPE NERR_ASSERT; 39 extern NERR_TYPE NERR_NOT_FOUND; 40 extern NERR_TYPE NERR_DUPLICATE; 41 extern NERR_TYPE NERR_NOMEM; 42 extern NERR_TYPE NERR_PARSE; 43 extern NERR_TYPE NERR_OUTOFRANGE; 44 extern NERR_TYPE NERR_SYSTEM; 45 extern NERR_TYPE NERR_IO; 46 extern NERR_TYPE NERR_LOCK; 47 extern NERR_TYPE NERR_DB; 48 extern NERR_TYPE NERR_EXISTS; 49 50 typedef struct _neo_err 51 { 52 int error; 53 int err_stack; 54 int flags; 55 char desc[256]; 56 const char *file; 57 const char *func; 58 int lineno; 59 /* internal use only */ 60 struct _neo_err *next; 61 } NEOERR; 62 63 /* Technically, we could do this in configure and detect what their compiler 64 * can handle, but for now... */ 65 #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 66 #define USE_C99_VARARG_MACROS 1 67 #elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 4) || defined (S_SPLINT_S) 68 #define USE_GNUC_VARARG_MACROS 1 69 #else 70 #error The compiler is missing support for variable-argument macros. 71 #endif 72 73 74 /* 75 * function: nerr_raise 76 * description: Use this method to create an error "exception" for 77 * return up the call chain 78 * arguments: using the macro, the function name, file, and lineno are 79 * automagically recorded for you. You just provide the 80 * error (from those listed above) and the printf-style 81 * reason. THIS IS A PRINTF STYLE FUNCTION, DO NOT PASS 82 * UNKNOWN STRING DATA AS THE FORMAT STRING. 83 * returns: a pointer to a NEOERR, or INTERNAL_ERR if allocation of 84 * NEOERR fails 85 */ 86 #if defined(USE_C99_VARARG_MACROS) 87 #define nerr_raise(e,f,...) \ 88 nerr_raisef(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f,__VA_ARGS__) 89 #elif defined(USE_GNUC_VARARG_MACROS) 90 #define nerr_raise(e,f,a...) \ 91 nerr_raisef(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f,##a) 92 #endif 93 94 NEOERR *nerr_raisef (const char *func, const char *file, int lineno, 95 NERR_TYPE error, const char *fmt, ...) 96 ATTRIBUTE_PRINTF(5,6); 97 98 99 100 #if defined(USE_C99_VARARG_MACROS) 101 #define nerr_raise_errno(e,f,...) \ 102 nerr_raise_errnof(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f,__VA_ARGS__) 103 #elif defined(USE_GNUC_VARARG_MACROS) 104 #define nerr_raise_errno(e,f,a...) \ 105 nerr_raise_errnof(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f,##a) 106 #endif 107 108 NEOERR *nerr_raise_errnof (const char *func, const char *file, int lineno, 109 int error, const char *fmt, ...) 110 ATTRIBUTE_PRINTF(5,6); 111 112 /* function: nerr_pass 113 * description: this function is used to pass an error up a level in the 114 * call chain (ie, if the error isn't handled at the 115 * current level). This allows us to track the traceback 116 * of the error. 117 * arguments: with the macro, the function name, file and lineno are 118 * automagically recorded. Just pass the error. 119 * returns: a pointer to an error 120 */ 121 #define nerr_pass(e) \ 122 nerr_passf(__PRETTY_FUNCTION__,__FILE__,__LINE__,e) 123 124 NEOERR *nerr_passf (const char *func, const char *file, int lineno, 125 NEOERR *err); 126 127 /* function: nerr_pass_ctx 128 * description: this function is used to pass an error up a level in the 129 * call chain (ie, if the error isn't handled at the 130 * current level). This allows us to track the traceback 131 * of the error. 132 * This version includes context information about lower 133 * errors 134 * arguments: with the macro, the function name, file and lineno are 135 * automagically recorded. Just pass the error and 136 * a printf format string giving more information about where 137 * the error is occuring. 138 * returns: a pointer to an error 139 */ 140 #if defined(USE_C99_VARARG_MACROS) 141 #define nerr_pass_ctx(e,f,...) \ 142 nerr_pass_ctxf(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f,__VA_ARGS__) 143 #elif defined(USE_GNUC_VARARG_MACROS) 144 #define nerr_pass_ctx(e,f,a...) \ 145 nerr_pass_ctxf(__PRETTY_FUNCTION__,__FILE__,__LINE__,e,f,##a) 146 #endif 147 148 NEOERR *nerr_pass_ctxf (const char *func, const char *file, int lineno, 149 NEOERR *err, const char *fmt, ...) 150 ATTRIBUTE_PRINTF(5,6); 151 152 /* function: nerr_log_error 153 * description: currently, this prints out the error to stderr, and 154 * free's the error chain 155 */ 156 void nerr_log_error (NEOERR *err); 157 158 #include "util/neo_str.h" 159 /* function: nerr_error_string 160 * description: returns the string associated with an error (the bottom 161 * level of the error chain) 162 * arguments: err - error 163 * str - string to which the data is appended 164 * returns: None - errors appending to the string are ignored 165 */ 166 void nerr_error_string (NEOERR *err, STRING *str); 167 168 /* function: nerr_error_traceback 169 * description: returns the full traceback of the error chain 170 * arguments: err - error 171 * str - string to which the data is appended 172 * returns: None - errors appending to the string are ignored 173 */ 174 void nerr_error_traceback (NEOERR *err, STRING *str); 175 176 /* function: nerr_ignore 177 * description: you should only call this if you actually handle the 178 * error (should I rename it?). Free's the error chain. 179 */ 180 void nerr_ignore (NEOERR **err); 181 182 /* function: nerr_register 183 * description: register an error type. This will assign a numeric value 184 * to the type, and keep track of the "pretty name" for it. 185 * arguments: err - pointer to a NERR_TYPE 186 * name - pretty name for the error type 187 * returns: NERR_NOMEM on no memory 188 */ 189 NEOERR *nerr_register (NERR_TYPE *err, const char *name); 190 191 /* function: nerr_init 192 * description: initialize the NEOERR system. Can be called more than once. 193 * Is not thread safe. This registers all of the built in 194 * error types as defined at the top of this file. If you don't 195 * call this, all exceptions will be returned as UnknownError. 196 * arguments: None 197 * returns: possibly NERR_NOMEM, but somewhat unlikely. Possibly an 198 * UnknownError if NERR_NOMEM hasn't been registered yet. 199 */ 200 NEOERR *nerr_init (void); 201 202 /* function: nerr_match 203 * description: nerr_match is used to walk the NEOERR chain and match 204 * the error against a specific error type. In exception 205 * parlance, this would be the equivalent of "catch". 206 * Typically, you can just compare a NEOERR against STATUS_OK 207 * or just test for true if you are checking for any error. 208 * arguments: err - the NEOERR that has an error. 209 * type - the NEOERR type, as registered with nerr_register 210 * returns: true on match 211 */ 212 int nerr_match (NEOERR *err, NERR_TYPE type); 213 214 /* function: nerr_handle 215 * description: nerr_handle is a convenience function. It is the equivalent 216 * of nerr_match, but it will also deallocate the error chain 217 * on a match. 218 * arguments: err - pointer to a pointer NEOERR 219 * type - the NEOERR type, as registered with nerr_register 220 * returns: true on match 221 */ 222 int nerr_handle (NEOERR **err, NERR_TYPE type); 223 224 __END_DECLS 225 226 #endif /* __NEO_ERR_H_ */ 227