commit f8a5e7a7327914847422e78ca23d16526d2e59eb
parent 164582d3a1c900fbd9a69c38d44d4f91c31dc4d1
Author: Robert Russell <robertrussell.72001@gmail.com>
Date: Sun, 13 Aug 2023 12:19:00 -0700
Capitalize assert and require
Overwriting libc assert is a bad idea. See the new comment for why.
Also capitalize require for consistency.
Maybe we should have a rule that all macros in RCX should be
capitalized, but I kind of like how likely, unlikely, and
unreachable look like keywords, so I'm leaving them as is for now.
Diffstat:
11 files changed, 40 insertions(+), 31 deletions(-)
diff --git a/inc/buffer.h b/inc/buffer.h
@@ -92,7 +92,7 @@ buf_ref(Buf b) {
static inline void
buf_drop(Buf b) {
BufHdr_ *h = (BufHdr_ *)b - 1;
- assert(h->refcnt > 0, "buf_drop: no references held");
+ ASSERT(h->refcnt > 0, "buf_drop: no references held");
h->refcnt -= 1;
if (h->refcnt == 0 && (h->flags & BUF_FLAG_FREE_))
free(h);
diff --git a/inc/debug.h b/inc/debug.h
@@ -4,21 +4,26 @@
#include "def.h"
-/* require is like assert from assert.h, but it never gets disabled and it
+/* REQUIRE is like assert from assert.h, but it never gets disabled and it
* takes an optional message like C11's static_assert. */
-#define require(cond, ...) ((void)((cond) || (throw( \
+#define REQUIRE(cond, ...) ((void)((cond) || (throw( \
"Assertion failed [%s:%d]: %s\n", \
__FILE__, __LINE__, VA_DEFAULT(,##__VA_ARGS__, #cond) \
), 0)))
-/* Replace standard assert with version that accepts an optional message. */
+/* ASSERT is like the libc assert except it accepts an optional message. The
+ * name is in all caps mostly to not conflict with the libc assert (which could
+ * be a problem if you include a library header that includes assert.h), but it
+ * also serves as a reminder that ASSERT is a macro that might not behave as
+ * expected; in particular, ASSERT does not evaluate its argument when NDEBUG
+ * is set! */
#ifdef NDEBUG
-#define assert(cond, ...) ((void)0)
+#define ASSERT(cond, ...) ((void)0)
#else
-#define assert require
+#define ASSERT REQUIRE
#endif
-#define unreachable require(0, "unreachable code reached")
+#define unreachable REQUIRE(0, "unreachable code reached")
/* Print the given formatted message to stderr followed by a newline,
* and then abort. */
diff --git a/inc/def.h b/inc/def.h
@@ -26,6 +26,8 @@
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define SWAP(a, b) do { \
+ /* The check in the array length is basically a static_assert. The
+ * isize cast is needed, for otherwise -1 becomes unsigned. */ \
u8 r_swap_temp_[sizeof(a) == sizeof(b) ? (isize)sizeof(a) : -1]; \
memcpy(&r_swap_temp_, &(a), sizeof(a)); \
memcpy(&(a), &(b), sizeof(a)); \
diff --git a/inc/dict.h b/inc/dict.h
@@ -14,6 +14,8 @@ typedef u64 (*RDictHashFunc)(void *k, u64 seed, RDictSpec *s);
typedef void *(*RDictAlloczFunc)(usize size);
typedef void (*RDictFreeFunc)(void *p);
+/* RDictSpec is for passing user settings in to the shared part of the
+ * implementation in dict.c. */
struct r_dict_spec {
usize ksize;
usize vsize;
@@ -94,7 +96,7 @@ static inline UNUSED bool R_DICT_METHOD(set,##__VA_ARGS__)(D *d, K k, V v) { \
return r > 0; \
} \
static inline UNUSED int R_DICT_METHOD(put,##__VA_ARGS__)(D *d, K k, V v) { \
- assert(d->d.niter == 0, "can not call put while iterating through dict"); \
+ ASSERT(d->d.niter == 0, "can not call put while iterating through dict"); \
u64 h = R_DICT_HASH(&k, d->d.seed, R_DICT_SPEC_(K,V)); /* Allow hash to be inlined. */ \
void *vp; int r = r_dict_insert(&d->d, &vp, &k, h, R_DICT_SPEC_(K,V)); \
if (r >= 0) *(V *)vp = v; \
@@ -106,6 +108,6 @@ static inline UNUSED bool R_DICT_METHOD(del,##__VA_ARGS__)(D *d, V *v, K k) { \
if (v) *v = r > 0 ? *(V *)vp : d->default_val; \
return r > 0; \
} \
-static inline UNUSED void R_DICT_METHOD(clr,##__VA_ARGS__)(D *d) { r_dict_clear((void *)d, R_DICT_SPEC_(K,V)); }
+static inline UNUSED void R_DICT_METHOD(clr,##__VA_ARGS__)(D *d) { r_dict_clear(&d->d, R_DICT_SPEC_(K,V)); }
#define R_DICT_DEFINE(D, K, V, ...) /* No op. Everything is static inline. */
\ No newline at end of file
diff --git a/inc/string.h b/inc/string.h
@@ -8,7 +8,7 @@
#include "utf8.h"
/* Usage: printf("...%.*s...", STR_FMT(s)) */
-#define STR_FMT(s) (assert(str_len(s) <= INT_MAX), (int)str_len(s)), str_bytes(s)
+#define STR_FMT(s) (ASSERT(str_len(s) <= INT_MAX), (int)str_len(s)), str_bytes(s)
typedef struct str Str;
typedef struct rc_str RcStr;
diff --git a/src/buffer.c b/src/buffer.c
@@ -5,7 +5,7 @@
Buf
buf_memory(void *mem, usize cap) {
- require(((uptr)mem & (alignof(BufHdr_) - 1)) == 0,
+ REQUIRE(((uptr)mem & (alignof(BufHdr_) - 1)) == 0,
"buf_memory: bad alignment");
BufHdr_ *h = mem;
*h = (BufHdr_){cap, 1, 0};
@@ -81,16 +81,16 @@ buf_ereallocz(Buf *b, usize cap) {
Str
buf_slice(Buf b, usize l, usize u) {
BufHdr_ *h = (BufHdr_ *)b - 1;
- assert(!(h->flags & BUF_FLAG_FREE_), "buf_slice: can not take "
+ ASSERT(!(h->flags & BUF_FLAG_FREE_), "buf_slice: can not take "
"non-reference-counted slice of reference-counted Buf");
usize cap = buf_cap(b);
if (l < 0) l += cap;
- assert(0 <= l && l <= cap, "buf_slice: lower index out of bounds");
+ ASSERT(0 <= l && l <= cap, "buf_slice: lower index out of bounds");
if (u < 0) u += cap;
- assert(0 <= u && u <= cap, "buf_slice: upper index out of bounds");
+ ASSERT(0 <= u && u <= cap, "buf_slice: upper index out of bounds");
return (Str){
.len = l < u ? u - l : 0,
@@ -103,10 +103,10 @@ buf_slice_rc_ref(Buf b, usize l, usize u) {
usize cap = buf_cap(b);
if (l < 0) l += cap;
- assert(0 <= l && l <= cap, "buf_slice_rc_ref: lower index out of bounds");
+ ASSERT(0 <= l && l <= cap, "buf_slice_rc_ref: lower index out of bounds");
if (u < 0) u += cap;
- assert(0 <= u && u <= cap, "buf_slice_rc_ref: upper index out of bounds");
+ ASSERT(0 <= u && u <= cap, "buf_slice_rc_ref: upper index out of bounds");
buf_ref(b);
return (RcStr){
diff --git a/src/str.c b/src/str.c
@@ -13,7 +13,7 @@
static char *
r_str_vcat(char *buf, usize len, va_list args) {
- assert(buf || len == 0);
+ ASSERT(buf || len == 0);
char *s;
usize need = 1; /* Null terminator */
@@ -110,7 +110,7 @@ r_str_count(char *s, char *sub) {
usize
r_str_split(char ***fields, char *s, char *sep, usize n) {
- assert(strcmp(sep, ""), "separator must be nonempty");
+ ASSERT(strcmp(sep, ""), "separator must be nonempty");
if (n == 0) {
n = r_str_count(s, sep) + 1;
diff --git a/src/string.c b/src/string.c
@@ -44,10 +44,10 @@ str_alloc_vprintf(Str *str, char *fmt, va_list args) {
Str
str_slice(Str s, isize l, isize u) {
if (l < 0) l += s.len;
- assert(0 <= l && l <= s.len, "str_slice: lower index out of bounds");
+ ASSERT(0 <= l && l <= s.len, "str_slice: lower index out of bounds");
if (u < 0) u += s.len;
- assert(0 <= u && u <= s.len, "str_slice: upper index out of bounds");
+ ASSERT(0 <= u && u <= s.len, "str_slice: upper index out of bounds");
return (Str){
.len = l < u ? u - l : 0,
diff --git a/src/unix.c b/src/unix.c
@@ -53,7 +53,7 @@ r_iovec_gather(void *dst, struct iovec **iov, usize *niov, usize n) {
if ((*iov)->iov_len > 0) break;
}
- assert(n == 0);
+ ASSERT(n == 0);
}
/* Note for future implementation of r_readv_all: Suppose readv completely
@@ -83,7 +83,7 @@ r_writev_all(int fd, struct iovec **iov, usize *niov) {
if ((*iov)->iov_len > 0) break;
}
- assert(nw == 0);
+ ASSERT(nw == 0);
}
return 0;
diff --git a/src/vmem.c b/src/vmem.c
@@ -13,16 +13,16 @@
usize
vmem_page_size(void) {
long ps = sysconf(_SC_PAGE_SIZE);
- require(ps > 0,
+ REQUIRE(ps > 0,
"vmem_page_size: unable to determine page size");
- require((ps & (ps - 1)) == 0,
+ REQUIRE((ps & (ps - 1)) == 0,
"vmem_page_size: page size not a power of 2");
return ps;
}
void *
vmem_alloc(void *p, usize size) {
- assert(((uptr)p & (uptr)(vmem_page_size() - 1)) == 0,
+ ASSERT(((uptr)p & (uptr)(vmem_page_size() - 1)) == 0,
"vmem_alloc: misaligned pointer");
int flags = MAP_PRIVATE | MAP_ANONYMOUS
| (p ? MAP_FIXED : 0);
@@ -33,7 +33,7 @@ vmem_alloc(void *p, usize size) {
void *
vmem_reserve(void *p, usize size, bool swap) {
- assert(((uptr)p & (uptr)(vmem_page_size() - 1)) == 0,
+ ASSERT(((uptr)p & (uptr)(vmem_page_size() - 1)) == 0,
"vmem_reserve: misaligned pointer");
int flags = MAP_PRIVATE | MAP_ANONYMOUS
| (p ? MAP_FIXED : 0)
@@ -45,9 +45,9 @@ vmem_reserve(void *p, usize size, bool swap) {
void *
vmem_open(usize *len, void *p, char *path, char *opt) {
- assert(((uptr)p & (uptr)(vmem_page_size() - 1)) == 0,
+ ASSERT(((uptr)p & (uptr)(vmem_page_size() - 1)) == 0,
"vmem_open: misaligned pointer");
- assert(strspn(opt, "crstwx") == strlen(opt),
+ ASSERT(strspn(opt, "crstwx") == strlen(opt),
"vmem_open: invalid option");
bool c = !!strchr(opt, 'c');
@@ -98,7 +98,7 @@ vmem_open(usize *len, void *p, char *path, char *opt) {
void
vmem_free(void *p, usize size) {
- assert(((uptr)p & (uptr)(vmem_page_size() - 1)) == 0,
+ ASSERT(((uptr)p & (uptr)(vmem_page_size() - 1)) == 0,
"vmem_free: misaligned pointer");
int ret = munmap(p, size);
/* munmap should never fail. */
diff --git a/tool/ucattab.c b/tool/ucattab.c
@@ -53,8 +53,8 @@ parse_cats(char *filename) {
/* We expect UnicodeData.txt to be sorted, but I can't find any
* guarantee of that in UAX #44. */
- assert(cp > prevcp);
- assert(!inrange || r_str_ends_with(name, "Last>"));
+ ASSERT(cp > prevcp);
+ ASSERT(!inrange || r_str_ends_with(name, "Last>"));
for (i32 c = prevcp+1; c <= cp; c++)
cats[c] = inrange || c == cp ? cat : cattoi("Cn");