1 #ifndef ERROR_H |
1 #ifndef ERROR_H |
2 #define ERROR_H |
2 #define ERROR_H |
3 |
3 |
4 /* |
4 /** |
|
5 * @file |
|
6 * |
5 * Error-handling functions |
7 * Error-handling functions |
6 */ |
8 */ |
7 #include <errno.h> |
9 #include <errno.h> |
8 |
10 |
9 /* |
11 /** |
10 * Type used for error codes is an explicitly *unsigned* int, meaning that error codes themselves are positive. |
12 * The type used for error codes is an explicitly *unsigned* int, meaning that error codes themselves are positive. |
11 * Negative error codes also exist in some places, and they are just a negative err_t. |
13 * Negative error codes (as signed ints) also exist in some places, and they are just a negative err_t. |
12 */ |
14 */ |
13 typedef unsigned int err_t; |
15 typedef unsigned int err_t; |
14 |
16 |
15 /** |
17 /** |
16 * Ways to interpret error_info.extra |
18 * Ways to interpret error_info.extra |
17 */ |
19 */ |
18 enum error_extra_types { |
20 enum error_extra_types { |
|
21 /** No extra info */ |
19 ERR_EXTRA_NONE = 0, |
22 ERR_EXTRA_NONE = 0, |
20 |
23 |
21 /** libc errno, using strerror() */ |
24 /** libc errno, using strerror() */ |
22 ERR_EXTRA_ERRNO, |
25 ERR_EXTRA_ERRNO, |
23 |
26 |
24 /** libc resolver, using gai_strerror() */ |
27 /** libc resolver, using gai_strerror() */ |
25 ERR_EXTRA_GAI, |
28 ERR_EXTRA_GAI, |
26 |
29 |
27 /** gnutls, using gnutls_strerror() */ |
30 /** GnuTLS, using gnutls_strerror() */ |
28 ERR_EXTRA_GNUTLS, |
31 ERR_EXTRA_GNUTLS, |
29 }; |
32 }; |
30 |
33 |
31 /** |
34 /** |
32 * List of defined error codes, organized mostly by function name |
35 * List of defined error codes, organized mostly by function name |
80 |
83 |
81 /** How to interpret .extra */ |
84 /** How to interpret .extra */ |
82 enum error_extra_types extra_type; |
85 enum error_extra_types extra_type; |
83 }; |
86 }; |
84 |
87 |
85 /* |
88 /** |
86 * An error code and associated extra infos |
89 * An error code and associated extra infos |
87 */ |
90 */ |
88 struct error_info { |
91 struct error_info { |
89 /* The base error code */ |
92 /** The base error code */ |
90 err_t code; |
93 err_t code; |
91 |
94 |
92 /* Additional detail info, usually some third-party error code */ |
95 /** Additional detail info, usually some third-party error code, as defined by the code's ERR_EXTRA_* */ |
93 int extra; |
96 int extra; |
94 }; |
97 }; |
95 |
98 |
96 /* |
99 /** |
97 * Translate an err_t into a function name. |
100 * Translate an err_t into a function name. |
98 */ |
101 */ |
99 const char *error_name (err_t code); |
102 const char *error_name (err_t code); |
100 |
103 |
101 /* |
104 /** |
102 * Maximum length of error messages returned by error_msg (including NUL byte) |
105 * Maximum length of error messages returned by error_msg (including NUL byte) |
103 */ |
106 */ |
104 #define ERROR_MSG_MAXLEN 1024 |
107 #define ERROR_MSG_MAXLEN 1024 |
105 |
108 |
106 /* |
109 /** |
107 * Translate an error_info into a message. |
110 * Translate an error_info into a message. |
108 * |
111 * |
109 * This is returned as a pointer into a statically allocated buffer. It is not re-entrant. |
112 * This is returned as a pointer into a statically allocated buffer. It is not re-entrant. |
110 */ |
113 */ |
111 const char *error_msg (const struct error_info *err); |
114 const char *error_msg (const struct error_info *err); |
112 |
115 |
113 /** No error, evaulates as logical false */ |
116 /** No error, evaulates as logical false */ |
114 #define SUCCESS (0) |
117 #define SUCCESS (0) |
115 |
118 |
116 /* Evaulates to error_info.code as lvalue */ |
119 /** Evaulates to error_info.code as lvalue */ |
117 #define ERROR_CODE(err_info_ptr) ((err_info_ptr)->code) |
120 #define ERROR_CODE(err_info_ptr) ((err_info_ptr)->code) |
118 |
121 |
119 /* Evaulates to error_info.extra as lvalue */ |
122 /** Evaulates to error_info.extra as lvalue */ |
120 #define ERROR_EXTRA(err_info_ptr) ((err_info_ptr)->extra) |
123 #define ERROR_EXTRA(err_info_ptr) ((err_info_ptr)->extra) |
121 |
124 |
122 /* Set error_info.code to SUCCESS, evaulates as zero */ |
125 /** Set error_info.code to SUCCESS, evaulates as zero */ |
123 #define RESET_ERROR(err_info_ptr) ((err_info_ptr)->code = SUCCESS) |
126 #define RESET_ERROR(err_info_ptr) ((err_info_ptr)->code = SUCCESS) |
124 |
127 |
125 /* Compare error_info.code != 0 */ |
128 /** Compare error_info.code != 0 */ |
126 #define IS_ERROR(err_info_ptr) (!!(err_info_ptr)->code) |
129 #define IS_ERROR(err_info_ptr) (!!(err_info_ptr)->code) |
127 |
130 |
128 /* Compare the err_code/err_extra for an err_info */ |
131 /** Compare the err_code/err_extra for an err_info */ |
129 #define MATCH_ERROR(err_info_ptr, err_code, err_extra) ((err_info_ptr)->code == (err_code) && (err_info_ptr)->extra == (err_extra)) |
132 #define MATCH_ERROR(err_info_ptr, err_code, err_extra) ((err_info_ptr)->code == (err_code) && (err_info_ptr)->extra == (err_extra)) |
130 |
133 |
131 /* Set error_info.code, but leave err_extra as-is. Evaluates to err_code */ |
134 /** Set error_info.code, but leave err_extra as-is. Evaluates to err_code */ |
132 #define SET_ERROR(err_info_ptr, err_code) ((err_info_ptr)->code = (err_code)) |
135 #define SET_ERROR(err_info_ptr, err_code) ((err_info_ptr)->code = (err_code)) |
133 |
136 |
134 /* Set error_info.code/extra. XXX: should evaluate to err_code */ |
137 /** Set error_info.code/extra. XXX: should evaluate to err_code */ |
135 #define _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) (err_info_ptr)->code = (err_code); (err_info_ptr)->extra = (err_extra) |
138 #define _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) (err_info_ptr)->code = (err_code); (err_info_ptr)->extra = (err_extra) |
136 #define SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra); } while (0) |
139 #define SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra); } while (0) |
137 |
140 |
138 /* Set error_info.code to err_code, and .extra to errno. XXX: should evaulate to err_code */ |
141 /** Set error_info.code to err_code, and .extra to errno. XXX: should evaulate to err_code */ |
139 #define _SET_ERROR_ERRNO(err_info_ptr, err_code) _SET_ERROR_EXTRA(err_info_ptr, err_code, errno); |
142 #define _SET_ERROR_ERRNO(err_info_ptr, err_code) _SET_ERROR_EXTRA(err_info_ptr, err_code, errno); |
140 #define SET_ERROR_ERRNO(err_info_ptr, err_code) SET_ERROR_EXTRA(err_info_ptr, err_code, errno); |
143 #define SET_ERROR_ERRNO(err_info_ptr, err_code) SET_ERROR_EXTRA(err_info_ptr, err_code, errno); |
141 |
144 |
142 /* Set error_info from another error_info. Evaluates to the new error_info */ |
145 /** Set error_info from another error_info. Evaluates to the new error_info */ |
143 #define SET_ERROR_INFO(err_info_ptr, from_ptr) (*err_info_ptr = *from_ptr) |
146 #define SET_ERROR_INFO(err_info_ptr, from_ptr) (*err_info_ptr = *from_ptr) |
144 |
147 |
145 /* Same as above, but also return err_code from func. XXX: use 'return SET_ERROR...' instead */ |
148 /** Same as above, but also return err_code from func. XXX: use 'return SET_ERROR...' instead */ |
146 #define RETURN_SET_ERROR(err_info_ptr, err_code) do { SET_ERROR(err_info_ptr, err_code); return (err_code); } while (0) |
149 #define RETURN_SET_ERROR(err_info_ptr, err_code) do { SET_ERROR(err_info_ptr, err_code); return (err_code); } while (0) |
147 #define RETURN_SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra); return (err_code); } while (0) |
150 #define RETURN_SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra); return (err_code); } while (0) |
148 #define RETURN_SET_ERROR_ERRNO(err_info_ptr, err_code) do { _SET_ERROR_ERRNO(err_info_ptr, err_code); return (err_code); } while (0) |
151 #define RETURN_SET_ERROR_ERRNO(err_info_ptr, err_code) do { _SET_ERROR_ERRNO(err_info_ptr, err_code); return (err_code); } while (0) |
149 #define RETURN_SET_ERROR_INFO(err_info_ptr, from_ptr) do { SET_ERROR_INFO(err_info_ptr, from_ptr); return (from_ptr->code); } while (0) |
152 #define RETURN_SET_ERROR_INFO(err_info_ptr, from_ptr) do { SET_ERROR_INFO(err_info_ptr, from_ptr); return (from_ptr->code); } while (0) |
150 |
153 |
151 /* Same as above, but also do a 'goto error' */ |
154 /** Same as above, but also do a 'goto error' */ |
152 #define JUMP_SET_ERROR(err_info_ptr, err_code) do { SET_ERROR(err_info_ptr, err_code); goto error; } while (0) |
155 #define JUMP_SET_ERROR(err_info_ptr, err_code) do { SET_ERROR(err_info_ptr, err_code); goto error; } while (0) |
153 #define JUMP_SET_ERROR_INFO(err_info_ptr, from_ptr) do { SET_ERROR_INFO(err_info_ptr, from_ptr); goto error; } while (0) |
156 #define JUMP_SET_ERROR_INFO(err_info_ptr, from_ptr) do { SET_ERROR_INFO(err_info_ptr, from_ptr); goto error; } while (0) |
154 |
157 |
155 #endif |
158 #endif |