rcx

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

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:
Minc/buffer.h | 2+-
Minc/debug.h | 17+++++++++++------
Minc/def.h | 2++
Minc/dict.h | 6++++--
Minc/string.h | 2+-
Msrc/buffer.c | 12++++++------
Msrc/str.c | 4++--
Msrc/string.c | 4++--
Msrc/unix.c | 4++--
Msrc/vmem.c | 14+++++++-------
Mtool/ucattab.c | 4++--
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");