blob: 6778081326dcc22f2844ca0bdd8df37db644a392 [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)
swissChili1e8b7562021-12-22 21:22:57 -080047#define NEARFL(f, l) __error.loc.line=l, __error.loc.file=f
swissChili36f2c692021-08-08 14:31:44 -070048#define _TRY(expr, m, c) \
49 { \
50 struct error __sub = (expr); \
51 if (__sub.code) \
52 { \
53 if (!__sub.loc.file || !__sub.loc.line) \
54 __sub.loc.file = __error.loc.file, \
55 __sub.loc.line = __error.loc.line; \
56 if (c) \
57 __sub.code = c; \
58 char *__m = m; \
59 if (__m) \
60 __sub.message = __m; \
61 E_DEBUG(__sub, #expr); \
62 return __sub; \
63 } \
swissChili6d02af42021-08-05 19:49:01 -070064 }
65#define TRY(expr) _TRY(expr, NULL, 0)
66#define TRY_ELSE(expr, c, ...) _TRY(expr, ehsprintf(__VA_ARGS__), c)
67#define OKAY() return __error
swissChili36f2c692021-08-08 14:31:44 -070068#define THROW(_c, ...) \
69 { \
70 __error.code = (_c); \
71 __error.message = ehsprintf(__VA_ARGS__); \
72 E_DEBUG(__error, "throwing"); \
73 return __error; \
swissChili6d02af42021-08-05 19:49:01 -070074 }
swissChili36f2c692021-08-08 14:31:44 -070075#define THROWSAFE(_c) \
76 { \
77 __error.code = (_c); \
78 __error.safe_state = true; \
79 E_DEBUG(__error, "safe"); \
80 return __error; \
swissChili6d02af42021-08-05 19:49:01 -070081 }
82
83#define IS_OKAY(e) ((e).code == EOK)
swissChili36f2c692021-08-08 14:31:44 -070084#define OKAY_IF(val) \
85 { \
86 struct error __sub_of = (val); \
87 if (IS_OKAY(__sub_of)) \
88 OKAY(); \
89 if (!__sub_of.safe_state) \
90 TRY(__sub_of); \
swissChili6d02af42021-08-05 19:49:01 -070091 }
92
93#define WARN_UNUSED __attribute__((warn_unused_result))
94
95// error heap string print formatted
96// returns a heap-allocated string.
97char *ehsprintf(const char *msg, ...);
98
99void ereport(struct error err);
swissChili36f2c692021-08-08 14:31:44 -0700100
101void edebug(struct error err, char *file, int line, const char *func, const char *why);
swissChilia7568dc2021-08-08 16:52:52 -0700102
103#define UNUSED(val) (void)(val)