author | Tero Marttila <terom@fixme.fi> |
Thu, 28 May 2009 00:35:02 +0300 | |
branch | new-lib-errors |
changeset 218 | 5229a5d098b2 |
parent 217 | 7728d6ec3abf |
permissions | -rw-r--r-- |
216 | 1 |
#include "error.h" |
2 |
#include "log.h" |
|
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
3 |
#include "str.h" |
216 | 4 |
|
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
5 |
#include <string.h> |
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
6 |
#include <stdlib.h> |
217 | 7 |
|
216 | 8 |
const struct error_type* error_lookup_code (const struct error_list *list, err_t code) |
9 |
{ |
|
10 |
const struct error_type *type; |
|
11 |
||
12 |
// find matching code |
|
13 |
for (type = list->list; type->code; type++) { |
|
14 |
if (type->code == code) |
|
15 |
// found |
|
16 |
return type; |
|
17 |
} |
|
18 |
||
19 |
// not found |
|
20 |
return NULL; |
|
21 |
} |
|
22 |
||
23 |
const struct error_type* error_lookup (const error_t *err) |
|
24 |
{ |
|
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
25 |
const struct error_list *list = NULL; |
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
26 |
const struct error_item *item; |
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
27 |
const struct error_type *type; |
216 | 28 |
|
29 |
// traverse stack |
|
30 |
for (item = err->cur; item && item >= err->stack; item--) { |
|
31 |
if (!list) |
|
32 |
// initial type |
|
33 |
list = item->list; |
|
34 |
||
35 |
// verify list/type |
|
36 |
if (!list) |
|
37 |
log_warn("Uknown type"); |
|
38 |
||
39 |
else if (!(type = error_lookup_code(list, item->code))) |
|
40 |
log_warn("Uknown code %#04x for list %s", item->code, list->name); |
|
41 |
||
42 |
else |
|
43 |
// expected list for next item |
|
44 |
list = type->sublist; |
|
45 |
} |
|
46 |
||
47 |
// return what we found |
|
48 |
return type; |
|
49 |
} |
|
50 |
||
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
51 |
const char* error_name (const struct error_list *list, err_t code) |
216 | 52 |
{ |
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
53 |
const struct error_type *type; |
216 | 54 |
|
55 |
// just do a lookup |
|
217 | 56 |
if ((type = error_lookup_code(list, code))) |
216 | 57 |
return "[unknown]"; |
58 |
||
59 |
else |
|
60 |
return type->name; |
|
61 |
} |
|
62 |
||
63 |
const char* error_msg (const error_t *err) |
|
64 |
{ |
|
65 |
// XXX: bad to have a single buffer |
|
66 |
static char buf[ERROR_MSG_MAX]; |
|
67 |
||
68 |
char *buf_ptr = buf; |
|
69 |
size_t buf_size = sizeof(buf); |
|
70 |
||
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
71 |
const struct error_list *list = NULL; |
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
72 |
const struct error_item *item; |
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
73 |
const struct error_type *type; |
216 | 74 |
|
75 |
// traverse stack |
|
76 |
for (item = err->cur; item && item >= err->stack; item--) { |
|
77 |
if (!list) |
|
78 |
// initial lookup table |
|
79 |
list = item->list; |
|
80 |
||
81 |
// verify list/type |
|
82 |
if (!list) { |
|
83 |
// no type info at all |
|
84 |
buf_ptr += str_advance(&buf_size, NULL, str_append_fmt(buf_ptr, buf_size, "[%#04x]", item->code)); |
|
85 |
||
86 |
} else if (!(type = error_lookup_code(list, item->code))) { |
|
87 |
// couldn't find code in list |
|
88 |
buf_ptr += str_advance(&buf_size, NULL, str_append_fmt(buf_ptr, buf_size, "[%s:%#02x]", list->name, item->code)); |
|
89 |
||
90 |
} else { |
|
91 |
// found code's type |
|
92 |
// delimit using colons, except at the end |
|
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
93 |
buf_ptr += str_advance(&buf_size, NULL, str_append_fmt(buf_ptr, buf_size, "[%s] %s%s", |
216 | 94 |
list->name, type->name, item == err->stack ? "" : ": " |
95 |
)); |
|
96 |
||
97 |
// expected list for next item |
|
98 |
list = type->sublist; |
|
99 |
} |
|
100 |
} |
|
101 |
||
102 |
// add info for extra |
|
103 |
if (err->extra_type != type->extra_type) { |
|
104 |
// type mismatch |
|
105 |
buf_ptr += str_advance(&buf_size, NULL, str_append_fmt(buf_ptr, buf_size, ": [error_extra type mismatch: %s <=> %s", |
|
106 |
err->extra_type ? err->extra_type->name : NULL, |
|
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
107 |
type->extra_type ? type->extra_type->name : NULL |
216 | 108 |
)); |
109 |
||
110 |
} else if (err->extra_type) { |
|
111 |
// add extra info |
|
112 |
buf_ptr += str_advance(&buf_size, NULL, str_append_fmt(buf_ptr, buf_size, ": %s", |
|
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
113 |
err->extra_type->msg_func(err->extra_type, &err->extra_value) |
216 | 114 |
)); |
115 |
||
116 |
} |
|
117 |
||
118 |
// ok, return message |
|
119 |
return buf; |
|
120 |
} |
|
121 |
||
122 |
bool error_cmp_eq (const error_t *a, const error_t *b) |
|
123 |
{ |
|
124 |
// XXX: implement |
|
125 |
return true; |
|
126 |
} |
|
127 |
||
217 | 128 |
void error_reset (error_t *err) |
129 |
{ |
|
130 |
memset(err, 0, sizeof(*err)); |
|
131 |
} |
|
132 |
||
216 | 133 |
/** |
134 |
* Advance error stack to next position, and return pointer. |
|
135 |
* |
|
136 |
* Returns NULL if the stack runs out of space. |
|
137 |
*/ |
|
138 |
struct error_item* error_next (error_t *err) |
|
139 |
{ |
|
140 |
if (!err->cur) |
|
141 |
// initial position |
|
142 |
return (err->cur = err->stack); |
|
143 |
||
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
144 |
else if (err->cur < err->stack + ERROR_DEPTH_MAX) |
216 | 145 |
return (err->cur++); |
146 |
||
147 |
else |
|
148 |
return NULL; |
|
149 |
} |
|
150 |
||
151 |
void error_set (error_t *err, const struct error_list *list, err_t code) |
|
152 |
{ |
|
153 |
struct error_item *item; |
|
154 |
||
155 |
// empty |
|
156 |
error_reset(err); |
|
157 |
||
158 |
// next |
|
159 |
if (!(item = error_next(err))) |
|
160 |
return; |
|
161 |
||
162 |
// store |
|
163 |
item->code = code; |
|
164 |
item->list = list; |
|
165 |
} |
|
166 |
||
167 |
void error_set_extra (error_t *err, const struct error_list *list, err_t code, const struct error_extra_type *type, union error_extra extra) |
|
168 |
{ |
|
169 |
struct error_item *item; |
|
170 |
||
171 |
// empty |
|
172 |
error_reset(err); |
|
173 |
||
174 |
// next |
|
175 |
if (!(item = error_next(err))) |
|
176 |
return; |
|
177 |
||
178 |
// store |
|
179 |
item->code = code; |
|
180 |
item->list = list; |
|
181 |
err->extra_type = type; |
|
182 |
err->extra_value = extra; |
|
183 |
} |
|
184 |
||
185 |
void error_push (error_t *err, const struct error_list *list, err_t code) |
|
186 |
{ |
|
187 |
struct error_item *item; |
|
188 |
||
189 |
// next |
|
190 |
if (!(item = error_next(err))) |
|
191 |
return; |
|
192 |
||
193 |
// store |
|
194 |
item->code = code; |
|
195 |
item->list = list; |
|
196 |
} |
|
197 |
||
198 |
void error_copy (error_t *dst, const error_t *src) |
|
199 |
{ |
|
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
200 |
const struct error_item *item; |
216 | 201 |
|
202 |
// reset |
|
203 |
error_reset(dst); |
|
204 |
||
205 |
// copy each item |
|
206 |
for (item = src->stack; src->cur && item <= src->cur; item++) |
|
207 |
// push it on separately |
|
208 |
error_push(dst, item->list, item->code); |
|
209 |
||
210 |
// store extra |
|
211 |
dst->extra_type = src->extra_type; |
|
212 |
dst->extra_value = src->extra_value; |
|
213 |
} |
|
214 |
||
215 |
/* |
|
216 |
* Weird trickery to call log_msg_va2 with the fmt's in the right order (prefix). |
|
217 |
* |
|
218 |
* XXX: log should provide similar functionality |
|
219 |
*/ |
|
220 |
void _error_abort_ (const char *fmt2, va_list fmtargs2, const char *fmt1, ...) |
|
221 |
{ |
|
222 |
va_list vargs; |
|
223 |
||
224 |
va_start(vargs, fmt1); |
|
225 |
_log_msg_va2(LOG_FATAL, "error_abort", fmt1, vargs, fmt2, fmtargs2); |
|
226 |
va_end(vargs); |
|
227 |
} |
|
228 |
||
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
229 |
void _error_abort (const char *file, int line, const char *func, const char *fmt, ...) |
216 | 230 |
{ |
231 |
va_list vargs; |
|
232 |
||
233 |
va_start(vargs, fmt); |
|
234 |
_error_abort_(fmt, vargs, "%s:%d[%s]", file, line, func); |
|
235 |
va_end(vargs); |
|
218
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
236 |
|
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
237 |
// then remember to die |
5229a5d098b2
some of spbot and lib compiles
Tero Marttila <terom@fixme.fi>
parents:
217
diff
changeset
|
238 |
abort(); |
216 | 239 |
} |
240 |