blob: 7577cdf03f956b7d454ec18e6d8be276ef1bc37f [file] [log] [blame]
swissChili6d02af42021-08-05 19:49:01 -07001#pragma once
2
3#include <stdbool.h>
4
5// Error handling code
6
7struct eloc
8{
9 int line;
10 char *file;
11};
12
13enum error_code
14{
15 EOK = 0,
16 /// Expected something but didn't get it. if this is in a
17 /// safe_state we should probably just re-try.
18 EEXPECTED,
19 /// An invalid token was present in the input
20 EINVALID,
21 /// A structure was malformed
22 EMALFORMED,
23 /// The arguments provided were invalid
24 EARGS,
25 /// An external resource (say, a file) was not found
26 ENOTFOUND,
27 /// This is unimplemented
28 EUNIMPL,
29};
30
31struct error
32{
33 enum error_code code;
34 // Is any state safe? I.e. can we continue or must we panic?
35 bool safe_state;
36 struct eloc loc;
37 char *message;
38};
39
swissChili36f2c692021-08-08 14:31:44 -070040#define E_DEBUG(_e, _m) // edebug(_e, __FILE__, __LINE__, __func__, _m)
41#define E_INIT() \
42 struct error __error = { 0 };
43#define NEARVAL(val) \
44 __error.loc.line = cons_line(val), \
45 __error.loc.file = cons_file(val)
swissChili6d02af42021-08-05 19:49:01 -070046#define NEARIS(is) (is)->getpos((is), &__error.loc.line, &__error.loc.file)
swissChili36f2c692021-08-08 14:31:44 -070047#define _TRY(expr, m, c) \
48 { \
49 struct error __sub = (expr); \
50 if (__sub.code) \
51 { \
52 if (!__sub.loc.file || !__sub.loc.line) \
53 __sub.loc.file = __error.loc.file, \
54 __sub.loc.line = __error.loc.line; \
55 if (c) \
56 __sub.code = c; \
57 char *__m = m; \
58 if (__m) \
59 __sub.message = __m; \
60 E_DEBUG(__sub, #expr); \
61 return __sub; \
62 } \
swissChili6d02af42021-08-05 19:49:01 -070063 }
64#define TRY(expr) _TRY(expr, NULL, 0)
65#define TRY_ELSE(expr, c, ...) _TRY(expr, ehsprintf(__VA_ARGS__), c)
66#define OKAY() return __error
swissChili36f2c692021-08-08 14:31:44 -070067#define THROW(_c, ...) \
68 { \
69 __error.code = (_c); \
70 __error.message = ehsprintf(__VA_ARGS__); \
71 E_DEBUG(__error, "throwing"); \
72 return __error; \
swissChili6d02af42021-08-05 19:49:01 -070073 }
swissChili36f2c692021-08-08 14:31:44 -070074#define THROWSAFE(_c) \
75 { \
76 __error.code = (_c); \
77 __error.safe_state = true; \
78 E_DEBUG(__error, "safe"); \
79 return __error; \
swissChili6d02af42021-08-05 19:49:01 -070080 }
81
82#define IS_OKAY(e) ((e).code == EOK)
swissChili36f2c692021-08-08 14:31:44 -070083#define OKAY_IF(val) \
84 { \
85 struct error __sub_of = (val); \
86 if (IS_OKAY(__sub_of)) \
87 OKAY(); \
88 if (!__sub_of.safe_state) \
89 TRY(__sub_of); \
swissChili6d02af42021-08-05 19:49:01 -070090 }
91
92#define WARN_UNUSED __attribute__((warn_unused_result))
93
94// error heap string print formatted
95// returns a heap-allocated string.
96char *ehsprintf(const char *msg, ...);
97
98void ereport(struct error err);
swissChili36f2c692021-08-08 14:31:44 -070099
100void edebug(struct error err, char *file, int line, const char *func, const char *why);
swissChilia7568dc2021-08-08 16:52:52 -0700101
102#define UNUSED(val) (void)(val)