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