MULE 0.0.1
Multi-Use Library Essentials
Loading...
Searching...
No Matches
base.h
1#pragma once
2/**
3 * @defgroup mod_base Base
4 * @brief What every module needs, included before anything else.
5 *
6 * Every header includes base.h first, so a program that includes any
7 * module gets all of this:
8 * - `_POSIX_C_SOURCE` set to 200809L, unless the program set it first.
9 * It only takes effect before the first system header, so include MULE
10 * before any of them.
11 * - `<stdbool.h>`, `<stddef.h>` and `<stdint.h>`.
12 * - `ckd_add`, `ckd_sub` and `ckd_mul` for overflow-checked arithmetic.
13 * They come from C23's `<stdckdint.h>` when the compiler has it, and
14 * from the gcc and clang builtins otherwise.
15 * - The `MULE_NODISCARD`, `MULE_UNUSED`, `MULE_NORETURN` and
16 * `MULE_PRINTF` attribute macros. They are left out of the signatures
17 * in this reference.
18 *
19 * ## Layout rules
20 *
21 * These are for changing the library, not using it.
22 * - One folder per module under src/, holding `name.h` and `name.c`. A
23 * module of only macros and static functions is `name.h` alone.
24 * - Every header includes `base/base.h` first, and include paths are
25 * relative to src/ (`#include "str/str.h"`).
26 * - A `.c` file includes headers only, never another `.c`. Each program's
27 * unity file includes every `.c` it needs. Any order works, because
28 * each `.c` includes the headers it uses, so clang-format may sort them.
29 * - The whole program is one translation unit, so `static` does not keep
30 * names apart. Static helpers carry the module prefix and a trailing `_`.
31 * - Something belongs here only once two modules use it.
32 *
33 * Targets are Unix with clang 17+ or gcc 13+. The floor is C11, written as
34 * C99. Attributes go through the MULE_ macros below, so a compiler without
35 * GNU attributes still builds the library.
36 * @{
37 */
38
39/** @cond */
40/* Feature macros only take effect before the first system header. */
41#ifndef _POSIX_C_SOURCE
42#define _POSIX_C_SOURCE 200809L
43#endif
44
45#include <stdbool.h>
46#include <stddef.h>
47#include <stdint.h>
48
49/* gcc ignores a (void) cast on warn_unused_result, so discard by assigning. */
50#ifdef __GNUC__
51#define MULE_NODISCARD __attribute__((warn_unused_result))
52#define MULE_UNUSED __attribute__((unused))
53#define MULE_NORETURN __attribute__((noreturn))
54#define MULE_PRINTF(fmt, args) __attribute__((format(printf, fmt, args)))
55#else
56#define MULE_NODISCARD
57#define MULE_UNUSED
58#define MULE_NORETURN _Noreturn
59#define MULE_PRINTF(fmt, args)
60#endif
61
62#if __has_include(<stdckdint.h>)
63#include <stdckdint.h>
64#else
65/* gcc 13 has the builtins but not the C23 header. */
66#define ckd_add(r, a, b) __builtin_add_overflow((a), (b), (r))
67#define ckd_sub(r, a, b) __builtin_sub_overflow((a), (b), (r))
68#define ckd_mul(r, a, b) __builtin_mul_overflow((a), (b), (r))
69#endif
70/** @endcond */
71
72/** @name Version
73 * The library's version, which follows Semantic Versioning. See
74 * CHANGELOG.md for what changed in each one.
75 * @{ */
76/** Bumped for breaking changes, once the version reaches 1.0.0. */
77#define MULE_VERSION_MAJOR 0
78/** Bumped for new features. Before 1.0.0, also for breaking changes. */
79#define MULE_VERSION_MINOR 0
80/** Bumped for fixes that change no behaviour a program relies on. */
81#define MULE_VERSION_PATCH 1
82/** All three numbers as a string, such as "0.0.1". */
83#define MULE_VERSION "0.0.1"
84/** @} */
85
86/** @} */