rcx

library of miscellaneous bits of C code
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

commit d3d88235076197305a01e6460f43ea302b8809d1
parent efabee7b081c5b9805bc3046e1c27eb54f45bd50
Author: Robert Russell <robertrussell.72001@gmail.com>
Date:   Wed,  1 Feb 2023 21:19:23 -0800

Tentatively add error handling module

This is so my libraries can have a consistent API for error handling, rather
than me doing it ad hoc every time, which is what I'm currently doing.

Functions that, e.g., return a nonnegative int on success should probably still
use negative integers to signal errors, because
	if (f(x) < 0) {...}
is much nicer than
	if (R_ERR(f(x))) {...}
Although I'd probably write
	rerr = f(x);
	if (R_ERR(rerr)) {...}
instead of the latter.

In the future it might be worth adding an error source in rcx for libc/posix
errors.

Diffstat:
MMakefile | 2++
Minc/rcx/all.h | 1+
Ainc/rcx/error.h | 34++++++++++++++++++++++++++++++++++
Asrc/error.c | 27+++++++++++++++++++++++++++
4 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -6,6 +6,7 @@ SRC =\ src/alloc.c\ src/bench.c\ src/bits.c\ + src/error.c\ src/log.c\ src/str.c\ src/unicode.c\ @@ -22,6 +23,7 @@ librcx.a: $(SRC:.c=.o) src/alloc.o: src/alloc.c inc/rcx/alloc.h inc/rcx/def.h inc/rcx/log.h inc/rcx/rcx.h inc/rcx/internal/util.h config.mk src/bench.o: src/bench.c inc/rcx/bench.h inc/rcx/def.h inc/rcx/log.h inc/rcx/rcx.h config.mk src/bits.o: src/bits.c inc/rcx/bits.h inc/rcx/def.h inc/rcx/rcx.h config.mk +src/error.o: src/error.c inc/rcx/def.h inc/rcx/error.h inc/rcx/log.h inc/rcx/rcx.h config.mk src/log.o: src/log.c inc/rcx/def.h inc/rcx/log.h inc/rcx/rcx.h config.mk src/opt.o: src/opt.c inc/rcx/def.h inc/rcx/opt.h inc/rcx/rcx.h config.mk src/str.o: src/str.c inc/rcx/alloc.h inc/rcx/def.h inc/rcx/log.h inc/rcx/rcx.h inc/rcx/str.h config.mk diff --git a/inc/rcx/all.h b/inc/rcx/all.h @@ -2,6 +2,7 @@ #include "rcx/alloc.h" #include "rcx/bits.h" #include "rcx/deque.h" +#include "rcx/error.h" #include "rcx/log.h" #include "rcx/opt.h" #include "rcx/rcx.h" diff --git a/inc/rcx/error.h b/inc/rcx/error.h @@ -0,0 +1,34 @@ +#pragma once + +#include "rcx/def.h" + +#define R_ERR(e) ((e).code != 0) + +typedef struct RError RError; +typedef struct RErrorSource RErrorSource; + +struct RErrorSource { + char *name; + /* Convert err to a string and write the result to buf, which must have + * length len >= 128. If the string does not fit in the given buffer, + * truncate in a source-specific manner (e.g., append an ellipsis). */ + void (*to_string)(char *buf, usize len, RError err); + /* Free any data associated with err. This field can be NULL. */ + void (*free)(RError err); +}; + +struct RError { + int code; /* 0 iff success */ + RErrorSource *src; + union { + i64 i; + u64 u; + double f; + char *s; + void *p; + } u; /* Subject to source-specific semantics. */ +}; + +void r_error_string(char *buf, usize len, RError err); +void r_error_fatal(RError err); +void r_error_drop(RError err); diff --git a/src/error.c b/src/error.c @@ -0,0 +1,27 @@ +#include <assert.h> + +#include "rcx/error.h" +#include "rcx/log.h" +#include "rcx/rcx.h" + +void +r_error_string(char *buf, usize len, RError err) { + assert(len >= 128); + err.src->to_string(buf, len, err); +} + +void +r_error_fatal(RError err) { + if (R_ERR(err)) { + char buf[128]; + r_error_string(buf, sizeof buf, err); + r_fatalf("%s", buf); + } +} + +void +r_error_drop(RError err) { + if (R_ERR(err)) { + err.src->free(err); + } +}