feat(headers): stddef/stdint/stdbool/limits/float/assert + features wiring

This commit is contained in:
2026-09-03 17:34:16 -04:00
parent ce517ad0d6
commit dec1017527
22 changed files with 2076 additions and 2 deletions
+45
View File
@@ -0,0 +1,45 @@
#ifndef VLIBC_ASSERT_H
#define VLIBC_ASSERT_H
/*
* vlibc — <assert.h>.
*
* The assert diagnostic macro. When NDEBUG is defined the macro expands to
* ((void)0) and the expression is not evaluated; otherwise a false result
* calls the library-internal __vlibc_assert_fail(), which writes the
* diagnostic to fd 2 through the raw syscall layer and terminates the
* process with __builtin_trap(). The helper deliberately does not depend on
* abort(), exit() or stdio: those land in later todos, and an assertion
* failure must work even when the runtime is half-initialized.
*
* static_assert is a C23 keyword; for C17 and older this header maps it onto
* _Static_assert, and _Static_assert itself remains usable in every mode.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
/* NDEBUG: strip the check entirely, matching the standard. */
#ifdef NDEBUG
#define assert(expr) ((void)0)
#else
/*
* Terminate after writing the failing assertion to fd 2; never returns.
* Implemented in src/internal/assert_fail.c. The name sits in the
* implementation-reserved namespace because it is libc plumbing, not
* public API.
*/
__attribute__((noreturn)) void
__vlibc_assert_fail(const char *expr, const char *file,
int line, // NOLINT(bugprone-reserved-identifier)
const char *func);
#define assert(expr) ((expr) ? (void)0 : __vlibc_assert_fail(#expr, __FILE__, __LINE__, __func__))
#endif
#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 202311L)
#define static_assert _Static_assert
#endif
#endif /* VLIBC_ASSERT_H */
+48
View File
@@ -0,0 +1,48 @@
#ifndef VLIBC_CPIO_H
#define VLIBC_CPIO_H
/*
* vlibc — <cpio.h>.
*
* Constants for cpio archive formats (POSIX). Constants only: the file and
* mode bits used in "newc"/odc archive headers, and the octal magic string
* of the odc format. The newc magic ("070701") is not standard and is
* deliberately omitted.
*/
#include <vlibc/features.h>
#if VLIBC_HAS_HEADER_CPIO_H
/* Octal magic of the odc ("old binary") archive format. */
#define MAGIC "070707"
/* Mode bits (permissions) of an archived entry. */
#define C_IRUSR 0000400
#define C_IWUSR 0000200
#define C_IXUSR 0000100
#define C_IRGRP 0000040
#define C_IWGRP 0000020
#define C_IXGRP 0000010
#define C_IROTH 0000004
#define C_IWOTH 0000002
#define C_IXOTH 0000001
/* Set-id and sticky bits of an archived entry. */
#define C_ISUID 0004000
#define C_ISGID 0002000
#define C_ISVTX 0001000
/* File type bits of an archived entry. */
#define C_ISDIR 0040000
#define C_ISFIFO 0010000
#define C_ISREG 0100000
#define C_ISBLK 0060000
#define C_ISCHR 0020000
#define C_ISCTG 0110000
#define C_ISLNK 0120000
#define C_ISSOCK 0140000
#endif /* VLIBC_HAS_HEADER_CPIO_H */
#endif /* VLIBC_CPIO_H */
+79
View File
@@ -0,0 +1,79 @@
#ifndef VLIBC_FLOAT_H
#define VLIBC_FLOAT_H
/*
* vlibc — <float.h>.
*
* Characteristics of floating-point types (C23). Every value is derived from
* compiler predefined macros (__FLT_MANT_DIG__, __DBL_MAX__, ...), so this
* header is fully self-contained. The values reflect the x86_64 SSE2
* environment: FLT_RADIX 2, IEC 60559 semantics for float, double and long
* double (the 80-bit extended type).
*
* FLT_ROUNDS is 1 (round to nearest): vlibc does not implement the floating
* environment yet, so the default rounding mode is always active. The fenv
* todo (#42) is expected to replace this with a live read of the x87/MXCSR
* control word.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
/* Base of all floating-point types. */
#define FLT_RADIX __FLT_RADIX__
/* Current rounding mode (see the header comment). */
#define FLT_ROUNDS 1
/* Evaluation method (x86_64: all operations use the type's own range). */
#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
/* IEC 60559 conformance of each type (C23). */
#define FLT_IS_IEC_60559 __FLT_IS_IEC_60559__
#define DBL_IS_IEC_60559 __DBL_IS_IEC_60559__
#define LDBL_IS_IEC_60559 __LDBL_IS_IEC_60559__
/* float. */
#define FLT_MANT_DIG __FLT_MANT_DIG__
#define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__
#define FLT_DIG __FLT_DIG__
#define FLT_MIN_EXP __FLT_MIN_EXP__
#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__
#define FLT_MAX_EXP __FLT_MAX_EXP__
#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__
#define FLT_MAX __FLT_MAX__
#define FLT_NORM_MAX __FLT_NORM_MAX__
#define FLT_EPSILON __FLT_EPSILON__
#define FLT_MIN __FLT_MIN__
#define FLT_TRUE_MIN __FLT_DENORM_MIN__
/* double. */
#define DBL_MANT_DIG __DBL_MANT_DIG__
#define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__
#define DBL_DIG __DBL_DIG__
#define DBL_MIN_EXP __DBL_MIN_EXP__
#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__
#define DBL_MAX_EXP __DBL_MAX_EXP__
#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__
#define DBL_MAX __DBL_MAX__
#define DBL_NORM_MAX __DBL_NORM_MAX__
#define DBL_EPSILON __DBL_EPSILON__
#define DBL_MIN __DBL_MIN__
#define DBL_TRUE_MIN __DBL_DENORM_MIN__
/* long double (x86_64: 80-bit extended). */
#define LDBL_MANT_DIG __LDBL_MANT_DIG__
#define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__
#define LDBL_DIG __LDBL_DIG__
#define LDBL_MIN_EXP __LDBL_MIN_EXP__
#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__
#define LDBL_MAX_EXP __LDBL_MAX_EXP__
#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__
#define LDBL_MAX __LDBL_MAX__
#define LDBL_NORM_MAX __LDBL_NORM_MAX__
#define LDBL_EPSILON __LDBL_EPSILON__
#define LDBL_MIN __LDBL_MIN__
#define LDBL_TRUE_MIN __LDBL_DENORM_MIN__
#endif /* VLIBC_FLOAT_H */
+32
View File
@@ -0,0 +1,32 @@
#ifndef VLIBC_ISO646_H
#define VLIBC_ISO646_H
/*
* vlibc — <iso646.h>.
*
* Alternative spellings for the bitwise and logical operators. C23 removed
* them from the language as alternative tokens, so this header provides them
* as macros; in C17 the spellings are lexed as tokens and the macros never
* fire, which makes the definitions harmless in both modes. In C++ they are
* part of the language, so no macros are defined there.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
#ifndef __cplusplus
#define and &&
#define and_eq &=
#define bitand &
#define bitor |
#define compl ~
#define not !
#define not_eq !=
#define or ||
#define or_eq |=
#define xor ^
#define xor_eq ^=
#endif
#endif /* VLIBC_ISO646_H */
+70
View File
@@ -0,0 +1,70 @@
#ifndef VLIBC_LIMITS_H
#define VLIBC_LIMITS_H
/*
* vlibc — <limits.h>.
*
* Sizes of integer types (C23). Every value is derived from compiler
* predefined macros (__CHAR_BIT__, __SCHAR_MAX__, __SIZEOF_INT__, ...), so
* this header is fully self-contained. char is signed on x86_64; the
* __CHAR_UNSIGNED__ branch keeps the header correct if that ever changes.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
/* Number of bits in the smallest addressable object. */
#define CHAR_BIT __CHAR_BIT__
/* Maximum number of bytes in a multibyte character (UTF-8 over 32-bit
* wchar_t needs at most 4). */
#define MB_LEN_MAX 4
/* Limits of the plain char types. */
#define SCHAR_MIN (-__SCHAR_MAX__ - 1)
#define SCHAR_MAX __SCHAR_MAX__
#define UCHAR_MAX (__SCHAR_MAX__ * 2 + 1)
#if defined(__CHAR_UNSIGNED__)
#define CHAR_MIN 0
#define CHAR_MAX UCHAR_MAX
#else
#define CHAR_MIN SCHAR_MIN
#define CHAR_MAX SCHAR_MAX
#endif
/* Limits of the short types. */
#define SHRT_MIN (-__SHRT_MAX__ - 1)
#define SHRT_MAX __SHRT_MAX__
#define USHRT_MAX (__SHRT_MAX__ * 2 + 1)
/* Limits of the int types. */
#define INT_MIN (-__INT_MAX__ - 1)
#define INT_MAX __INT_MAX__
#define UINT_MAX (__INT_MAX__ * 2U + 1U)
/* Limits of the long types (x86_64 LP64: 64-bit). */
#define LONG_MIN (-__LONG_MAX__ - 1L)
#define LONG_MAX __LONG_MAX__
#define ULONG_MAX (__LONG_MAX__ * 2UL + 1UL)
/* Limits of the long long types. */
#define LLONG_MIN (-__LONG_LONG_MAX__ - 1LL)
#define LLONG_MAX __LONG_LONG_MAX__
#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1ULL)
/* Width of each integer type, in bits (C23). */
#define BOOL_WIDTH 1
#define CHAR_WIDTH __CHAR_BIT__
#define SCHAR_WIDTH __CHAR_BIT__
#define UCHAR_WIDTH __CHAR_BIT__
#define SHRT_WIDTH (__SIZEOF_SHORT__ * __CHAR_BIT__)
#define USHRT_WIDTH (__SIZEOF_SHORT__ * __CHAR_BIT__)
#define INT_WIDTH (__SIZEOF_INT__ * __CHAR_BIT__)
#define UINT_WIDTH (__SIZEOF_INT__ * __CHAR_BIT__)
#define LONG_WIDTH (__SIZEOF_LONG__ * __CHAR_BIT__)
#define ULONG_WIDTH (__SIZEOF_LONG__ * __CHAR_BIT__)
#define LLONG_WIDTH (__SIZEOF_LONG_LONG__ * __CHAR_BIT__)
#define ULLONG_WIDTH (__SIZEOF_LONG_LONG__ * __CHAR_BIT__)
#endif /* VLIBC_LIMITS_H */
+27
View File
@@ -0,0 +1,27 @@
#ifndef VLIBC_STDALIGN_H
#define VLIBC_STDALIGN_H
/*
* vlibc — <stdalign.h>.
*
* In C23 alignas and alignof are keywords, so this header defines only the
* feature-test macros __alignas_is_defined and __alignof_is_defined. In C17
* (and older) it additionally maps them onto the _Alignas/_Alignof keywords.
* In C++ the two names are keywords as well.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
#ifndef __cplusplus
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 202311L
#define alignas _Alignas
#define alignof _Alignof
#endif
#endif
#define __alignas_is_defined 1
#define __alignof_is_defined 1
#endif /* VLIBC_STDALIGN_H */
+24
View File
@@ -0,0 +1,24 @@
#ifndef VLIBC_STDARG_H
#define VLIBC_STDARG_H
/*
* vlibc — <stdarg.h>.
*
* Variable argument lists. The entire header defers to the compiler's
* builtin support: __builtin_va_list names the ABI's va_list layout and the
* __builtin_va_* entry points manipulate it. Nothing here depends on a
* system header.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
typedef __builtin_va_list va_list;
#define va_start(ap, last) __builtin_va_start((ap), (last))
#define va_end(ap) __builtin_va_end((ap))
#define va_arg(ap, type) __builtin_va_arg((ap), type)
#define va_copy(dst, src) __builtin_va_copy((dst), (src))
#endif /* VLIBC_STDARG_H */
+186
View File
@@ -0,0 +1,186 @@
#ifndef VLIBC_STDATOMIC_H
#define VLIBC_STDATOMIC_H
/*
* vlibc — <stdatomic.h>.
*
* Atomics (C23). All operations defer to the GCC __atomic_* builtins, the
* same idiom src/internal/atomic.h uses: on x86_64 every standard atomic
* type here is lock-free in hardware, so the builtins inline to plain
* instructions and never call into libatomic. The header is fully
* self-contained (no system stdatomic.h) and compiles as C17-style code too,
* since _Atomic remains a keyword.
*
* The atomic_* operations are function-like macros over the polymorphic
* builtins (C23 allows any atomic operation to be implemented as a macro),
* which keeps them type-generic across every atomic_* type without a
* _Generic dispatch table.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Memory ordering. The enum values are the GCC __ATOMIC_* constants. */
typedef enum
{
memory_order_relaxed = __ATOMIC_RELAXED,
memory_order_consume = __ATOMIC_CONSUME,
memory_order_acquire = __ATOMIC_ACQUIRE,
memory_order_release = __ATOMIC_RELEASE,
memory_order_acq_rel = __ATOMIC_ACQ_REL,
memory_order_seq_cst = __ATOMIC_SEQ_CST
} memory_order;
/* Lock-free guarantees for each type (0: never, 1: sometimes, 2: always). */
#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
/* Atomic scalar types. */
typedef _Atomic _Bool atomic_bool;
typedef _Atomic char atomic_char;
typedef _Atomic signed char atomic_schar;
typedef _Atomic unsigned char atomic_uchar;
typedef _Atomic short atomic_short;
typedef _Atomic unsigned short atomic_ushort;
typedef _Atomic int atomic_int;
typedef _Atomic unsigned int atomic_uint;
typedef _Atomic long atomic_long;
typedef _Atomic unsigned long atomic_ulong;
typedef _Atomic long long atomic_llong;
typedef _Atomic unsigned long long atomic_ullong;
typedef _Atomic __CHAR16_TYPE__ atomic_char16_t;
typedef _Atomic __CHAR32_TYPE__ atomic_char32_t;
typedef _Atomic __WCHAR_TYPE__ atomic_wchar_t;
typedef _Atomic int_least8_t atomic_int_least8_t;
typedef _Atomic uint_least8_t atomic_uint_least8_t;
typedef _Atomic int_least16_t atomic_int_least16_t;
typedef _Atomic uint_least16_t atomic_uint_least16_t;
typedef _Atomic int_least32_t atomic_int_least32_t;
typedef _Atomic uint_least32_t atomic_uint_least32_t;
typedef _Atomic int_least64_t atomic_int_least64_t;
typedef _Atomic uint_least64_t atomic_uint_least64_t;
typedef _Atomic int_fast8_t atomic_int_fast8_t;
typedef _Atomic uint_fast8_t atomic_uint_fast8_t;
typedef _Atomic int_fast16_t atomic_int_fast16_t;
typedef _Atomic uint_fast16_t atomic_uint_fast16_t;
typedef _Atomic int_fast32_t atomic_int_fast32_t;
typedef _Atomic uint_fast32_t atomic_uint_fast32_t;
typedef _Atomic int_fast64_t atomic_int_fast64_t;
typedef _Atomic uint_fast64_t atomic_uint_fast64_t;
typedef _Atomic intptr_t atomic_intptr_t;
typedef _Atomic uintptr_t atomic_uintptr_t;
typedef _Atomic size_t atomic_size_t;
typedef _Atomic ptrdiff_t atomic_ptrdiff_t;
typedef _Atomic intmax_t atomic_intmax_t;
typedef _Atomic uintmax_t atomic_uintmax_t;
/* The only type the standard guarantees to be lock-free. */
typedef _Atomic unsigned int atomic_flag;
/* Initializer for an atomic_flag object. */
#define ATOMIC_FLAG_INIT 0
/*
* The operations below are macros because the __atomic_* builtins are
* polymorphic: they accept any 1/2/4/8-byte scalar or pointer type, so a
* single macro serves every atomic_* type. The (object) argument is the
* address of the atomic object, matching the standard's function signatures.
*/
/* Initialize the atomic object to value (a relaxed store). */
#define atomic_init(object, value) __atomic_store_n((object), (value), __ATOMIC_RELAXED)
/* Load the current value. */
#define atomic_load(object) __atomic_load_n((object), __ATOMIC_SEQ_CST)
#define atomic_load_explicit(object, order) __atomic_load_n((object), (order))
/* Store value. */
#define atomic_store(object, value) __atomic_store_n((object), (value), __ATOMIC_SEQ_CST)
#define atomic_store_explicit(object, value, order) __atomic_store_n((object), (value), (order))
/* Exchange object's value with desired; returns the previous value. */
#define atomic_exchange(object, desired) __atomic_exchange_n((object), (desired), __ATOMIC_SEQ_CST)
#define atomic_exchange_explicit(object, desired, order) \
__atomic_exchange_n((object), (desired), (order))
/*
* Compare-and-swap: store desired into object iff *object equals *expected.
* On failure *expected is updated with the actual value and the macro
* returns false. The first memorder governs the read-modify-write on
* success, the second the load on failure.
*/
#define atomic_compare_exchange_strong(object, expected, desired) \
__atomic_compare_exchange_n((object), (expected), (desired), 0, __ATOMIC_SEQ_CST, \
__ATOMIC_SEQ_CST)
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
__atomic_compare_exchange_n((object), (expected), (desired), 0, (success), (failure))
#define atomic_compare_exchange_weak(object, expected, desired) \
__atomic_compare_exchange_n((object), (expected), (desired), 1, __ATOMIC_SEQ_CST, \
__ATOMIC_SEQ_CST)
#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
__atomic_compare_exchange_n((object), (expected), (desired), 1, (success), (failure))
/* Fetch and add; returns the previous value. */
#define atomic_fetch_add(object, operand) __atomic_fetch_add((object), (operand), __ATOMIC_SEQ_CST)
#define atomic_fetch_add_explicit(object, operand, order) \
__atomic_fetch_add((object), (operand), (order))
/* Fetch and subtract; returns the previous value. */
#define atomic_fetch_sub(object, operand) __atomic_fetch_sub((object), (operand), __ATOMIC_SEQ_CST)
#define atomic_fetch_sub_explicit(object, operand, order) \
__atomic_fetch_sub((object), (operand), (order))
/* Fetch and bitwise-or; returns the previous value. */
#define atomic_fetch_or(object, operand) __atomic_fetch_or((object), (operand), __ATOMIC_SEQ_CST)
#define atomic_fetch_or_explicit(object, operand, order) \
__atomic_fetch_or((object), (operand), (order))
/* Fetch and bitwise-xor; returns the previous value. */
#define atomic_fetch_xor(object, operand) __atomic_fetch_xor((object), (operand), __ATOMIC_SEQ_CST)
#define atomic_fetch_xor_explicit(object, operand, order) \
__atomic_fetch_xor((object), (operand), (order))
/* Fetch and bitwise-and; returns the previous value. */
#define atomic_fetch_and(object, operand) __atomic_fetch_and((object), (operand), __ATOMIC_SEQ_CST)
#define atomic_fetch_and_explicit(object, operand, order) \
__atomic_fetch_and((object), (operand), (order))
/* atomic_flag: test-and-set (returns the previous flag value). */
#define atomic_flag_test_and_set(object) __atomic_test_and_set((object), __ATOMIC_SEQ_CST)
#define atomic_flag_test_and_set_explicit(object, order) __atomic_test_and_set((object), (order))
/* atomic_flag: clear. */
#define atomic_flag_clear(object) __atomic_clear((object), __ATOMIC_SEQ_CST)
#define atomic_flag_clear_explicit(object, order) __atomic_clear((object), (order))
/* Non-zero iff *object is always lock-free. */
#define atomic_is_lock_free(object) __atomic_is_lock_free(sizeof *(object), (object))
/* Fences. */
#define atomic_thread_fence(order) __atomic_thread_fence((order))
#define atomic_signal_fence(order) __atomic_signal_fence((order))
/* Carry a dependency through a load without a synchronization edge. */
#define kill_dependency(y) (y)
#ifdef __cplusplus
}
#endif
#endif /* VLIBC_STDATOMIC_H */
+496
View File
@@ -0,0 +1,496 @@
#ifndef VLIBC_STDBIT_H
#define VLIBC_STDBIT_H
/*
* vlibc — <stdbit.h>.
*
* Bit and byte manipulation (C23 7.18). Every per-width operation is a
* static inline function over the GCC counting builtins
* (__builtin_clz/clzl/clzll, __builtin_ctz/ctzl/ctzll,
* __builtin_popcount/popcountl/popcountll), so no call escapes into the
* library. The type-generic names (stdc_leading_zeros, ...) dispatch through
* _Generic to the per-width functions; signed arguments convert to the
* unsigned type of the same rank, which preserves the bit pattern exactly as
* C23 specifies. Widths match x86_64: int is 32-bit, long is 64-bit.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
#include <limits.h>
/* stdc_leading_zeros: number of 0 bits before the first 1 bit, or the width. */
static inline unsigned int
stdc_leading_zeros_uc(unsigned char x)
{
return x == 0 ? 8u : (unsigned int)(__builtin_clz(x) - 24);
}
static inline unsigned int
stdc_leading_zeros_us(unsigned short x)
{
return x == 0 ? 16u : (unsigned int)(__builtin_clz(x) - 16);
}
static inline unsigned int
stdc_leading_zeros_ui(unsigned int x)
{
return x == 0 ? 32u : (unsigned int)__builtin_clz(x);
}
static inline unsigned int
stdc_leading_zeros_ul(unsigned long x)
{
return x == 0 ? 64u : (unsigned int)__builtin_clzl(x);
}
static inline unsigned int
stdc_leading_zeros_ull(unsigned long long x)
{
return x == 0 ? 64u : (unsigned int)__builtin_clzll(x);
}
/* stdc_leading_ones: number of 1 bits before the first 0 bit, or the width. */
static inline unsigned int
stdc_leading_ones_uc(unsigned char x)
{
return x == UCHAR_MAX ? 8u : (unsigned int)(__builtin_clz((unsigned char)~x) - 24);
}
static inline unsigned int
stdc_leading_ones_us(unsigned short x)
{
return x == USHRT_MAX ? 16u : (unsigned int)(__builtin_clz((unsigned short)~x) - 16);
}
static inline unsigned int
stdc_leading_ones_ui(unsigned int x)
{
return x == UINT_MAX ? 32u : (unsigned int)__builtin_clz(~x);
}
static inline unsigned int
stdc_leading_ones_ul(unsigned long x)
{
return x == ULONG_MAX ? 64u : (unsigned int)__builtin_clzl(~x);
}
static inline unsigned int
stdc_leading_ones_ull(unsigned long long x)
{
return x == ULLONG_MAX ? 64u : (unsigned int)__builtin_clzll(~x);
}
/* stdc_trailing_zeros: number of 0 bits after the last 1 bit, or the width. */
static inline unsigned int
stdc_trailing_zeros_uc(unsigned char x)
{
return x == 0 ? 8u : (unsigned int)__builtin_ctz(x);
}
static inline unsigned int
stdc_trailing_zeros_us(unsigned short x)
{
return x == 0 ? 16u : (unsigned int)__builtin_ctz(x);
}
static inline unsigned int
stdc_trailing_zeros_ui(unsigned int x)
{
return x == 0 ? 32u : (unsigned int)__builtin_ctz(x);
}
static inline unsigned int
stdc_trailing_zeros_ul(unsigned long x)
{
return x == 0 ? 64u : (unsigned int)__builtin_ctzl(x);
}
static inline unsigned int
stdc_trailing_zeros_ull(unsigned long long x)
{
return x == 0 ? 64u : (unsigned int)__builtin_ctzll(x);
}
/* stdc_trailing_ones: number of 1 bits after the last 0 bit, or the width. */
static inline unsigned int
stdc_trailing_ones_uc(unsigned char x)
{
return x == UCHAR_MAX ? 8u : (unsigned int)__builtin_ctz((unsigned char)~x);
}
static inline unsigned int
stdc_trailing_ones_us(unsigned short x)
{
return x == USHRT_MAX ? 16u : (unsigned int)__builtin_ctz((unsigned short)~x);
}
static inline unsigned int
stdc_trailing_ones_ui(unsigned int x)
{
return x == UINT_MAX ? 32u : (unsigned int)__builtin_ctz(~x);
}
static inline unsigned int
stdc_trailing_ones_ul(unsigned long x)
{
return x == ULONG_MAX ? 64u : (unsigned int)__builtin_ctzl(~x);
}
static inline unsigned int
stdc_trailing_ones_ull(unsigned long long x)
{
return x == ULLONG_MAX ? 64u : (unsigned int)__builtin_ctzll(~x);
}
/*
* stdc_first_*: index (from the most significant bit) of the first zero/one
* bit, or the width when no such bit exists. By construction, the index of
* the first zero from the top equals the count of leading ones, and so on.
*/
static inline unsigned int
stdc_first_leading_zero_uc(unsigned char x)
{
return stdc_leading_ones_uc(x);
}
static inline unsigned int
stdc_first_leading_zero_us(unsigned short x)
{
return stdc_leading_ones_us(x);
}
static inline unsigned int
stdc_first_leading_zero_ui(unsigned int x)
{
return stdc_leading_ones_ui(x);
}
static inline unsigned int
stdc_first_leading_zero_ul(unsigned long x)
{
return stdc_leading_ones_ul(x);
}
static inline unsigned int
stdc_first_leading_zero_ull(unsigned long long x)
{
return stdc_leading_ones_ull(x);
}
static inline unsigned int
stdc_first_leading_one_uc(unsigned char x)
{
return stdc_leading_zeros_uc(x);
}
static inline unsigned int
stdc_first_leading_one_us(unsigned short x)
{
return stdc_leading_zeros_us(x);
}
static inline unsigned int
stdc_first_leading_one_ui(unsigned int x)
{
return stdc_leading_zeros_ui(x);
}
static inline unsigned int
stdc_first_leading_one_ul(unsigned long x)
{
return stdc_leading_zeros_ul(x);
}
static inline unsigned int
stdc_first_leading_one_ull(unsigned long long x)
{
return stdc_leading_zeros_ull(x);
}
static inline unsigned int
stdc_first_trailing_zero_uc(unsigned char x)
{
return stdc_trailing_ones_uc(x);
}
static inline unsigned int
stdc_first_trailing_zero_us(unsigned short x)
{
return stdc_trailing_ones_us(x);
}
static inline unsigned int
stdc_first_trailing_zero_ui(unsigned int x)
{
return stdc_trailing_ones_ui(x);
}
static inline unsigned int
stdc_first_trailing_zero_ul(unsigned long x)
{
return stdc_trailing_ones_ul(x);
}
static inline unsigned int
stdc_first_trailing_zero_ull(unsigned long long x)
{
return stdc_trailing_ones_ull(x);
}
static inline unsigned int
stdc_first_trailing_one_uc(unsigned char x)
{
return stdc_trailing_zeros_uc(x);
}
static inline unsigned int
stdc_first_trailing_one_us(unsigned short x)
{
return stdc_trailing_zeros_us(x);
}
static inline unsigned int
stdc_first_trailing_one_ui(unsigned int x)
{
return stdc_trailing_zeros_ui(x);
}
static inline unsigned int
stdc_first_trailing_one_ul(unsigned long x)
{
return stdc_trailing_zeros_ul(x);
}
static inline unsigned int
stdc_first_trailing_one_ull(unsigned long long x)
{
return stdc_trailing_zeros_ull(x);
}
/* stdc_count_ones: number of 1 bits. */
static inline unsigned int
stdc_count_ones_uc(unsigned char x)
{
return (unsigned int)__builtin_popcount(x);
}
static inline unsigned int
stdc_count_ones_us(unsigned short x)
{
return (unsigned int)__builtin_popcount(x);
}
static inline unsigned int
stdc_count_ones_ui(unsigned int x)
{
return (unsigned int)__builtin_popcount(x);
}
static inline unsigned int
stdc_count_ones_ul(unsigned long x)
{
return (unsigned int)__builtin_popcountl(x);
}
static inline unsigned int
stdc_count_ones_ull(unsigned long long x)
{
return (unsigned int)__builtin_popcountll(x);
}
/* stdc_count_zeros: number of 0 bits. */
static inline unsigned int
stdc_count_zeros_uc(unsigned char x)
{
return 8u - stdc_count_ones_uc(x);
}
static inline unsigned int
stdc_count_zeros_us(unsigned short x)
{
return 16u - stdc_count_ones_us(x);
}
static inline unsigned int
stdc_count_zeros_ui(unsigned int x)
{
return 32u - stdc_count_ones_ui(x);
}
static inline unsigned int
stdc_count_zeros_ul(unsigned long x)
{
return 64u - stdc_count_ones_ul(x);
}
static inline unsigned int
stdc_count_zeros_ull(unsigned long long x)
{
return 64u - stdc_count_ones_ull(x);
}
/* stdc_has_single_bit: true iff exactly one bit is set. */
static inline _Bool
stdc_has_single_bit_uc(unsigned char x)
{
return x != 0 && (x & (x - 1U)) == 0;
}
static inline _Bool
stdc_has_single_bit_us(unsigned short x)
{
return x != 0 && (x & (x - 1U)) == 0;
}
static inline _Bool
stdc_has_single_bit_ui(unsigned int x)
{
return x != 0 && (x & (x - 1U)) == 0;
}
static inline _Bool
stdc_has_single_bit_ul(unsigned long x)
{
return x != 0 && (x & (x - 1UL)) == 0;
}
static inline _Bool
stdc_has_single_bit_ull(unsigned long long x)
{
return x != 0 && (x & (x - 1ULL)) == 0;
}
/* stdc_bit_width: bits needed to represent x (0 for 0, 1 for 1). */
static inline unsigned int
stdc_bit_width_uc(unsigned char x)
{
return x == 0 ? 0u : (unsigned int)(32 - __builtin_clz(x));
}
static inline unsigned int
stdc_bit_width_us(unsigned short x)
{
return x == 0 ? 0u : (unsigned int)(32 - __builtin_clz(x));
}
static inline unsigned int
stdc_bit_width_ui(unsigned int x)
{
return x == 0 ? 0u : (unsigned int)(32 - __builtin_clz(x));
}
static inline unsigned int
stdc_bit_width_ul(unsigned long x)
{
return x == 0 ? 0u : (unsigned int)(64 - __builtin_clzl(x));
}
static inline unsigned int
stdc_bit_width_ull(unsigned long long x)
{
return x == 0 ? 0u : (unsigned int)(64 - __builtin_clzll(x));
}
/* stdc_bit_floor: largest power of 2 not greater than x (0 for 0). */
static inline unsigned char
stdc_bit_floor_uc(unsigned char x)
{
return (unsigned char)(x == 0 ? 0 : (1u << (32 - __builtin_clz(x) - 1)));
}
static inline unsigned short
stdc_bit_floor_us(unsigned short x)
{
return (unsigned short)(x == 0 ? 0 : (1u << (32 - __builtin_clz(x) - 1)));
}
static inline unsigned int
stdc_bit_floor_ui(unsigned int x)
{
return x == 0 ? 0u : (1u << (32 - __builtin_clz(x) - 1));
}
static inline unsigned long
stdc_bit_floor_ul(unsigned long x)
{
return x == 0 ? 0ul : (1ul << (64 - __builtin_clzl(x) - 1));
}
static inline unsigned long long
stdc_bit_floor_ull(unsigned long long x)
{
return x == 0 ? 0ull : (1ull << (64 - __builtin_clzll(x) - 1));
}
/*
* stdc_bit_ceil: smallest power of 2 not less than x. The result is
* undefined when it is not representable in the type of x, per C23.
*/
static inline unsigned char
stdc_bit_ceil_uc(unsigned char x)
{
return (unsigned char)(x <= 1 ? 1 : (1u << (32 - __builtin_clz(x - 1))));
}
static inline unsigned short
stdc_bit_ceil_us(unsigned short x)
{
return (unsigned short)(x <= 1 ? 1 : (1u << (32 - __builtin_clz(x - 1))));
}
static inline unsigned int
stdc_bit_ceil_ui(unsigned int x)
{
return x <= 1 ? 1u : (1u << (32 - __builtin_clz(x - 1)));
}
static inline unsigned long
stdc_bit_ceil_ul(unsigned long x)
{
return x <= 1 ? 1ul : (1ul << (64 - __builtin_clzl(x - 1)));
}
static inline unsigned long long
stdc_bit_ceil_ull(unsigned long long x)
{
return x <= 1 ? 1ull : (1ull << (64 - __builtin_clzll(x - 1)));
}
/*
* Type-generic dispatch: map the (lvalue-converted) argument type to the
* per-width function. Signed types route to the unsigned function of the
* same rank, which preserves the bit pattern as C23 requires.
*/
#define VLIBC_STDBIT_DISPATCH(fn, x) \
_Generic((x), \
_Bool: fn##_uc, \
char: fn##_uc, \
signed char: fn##_uc, \
unsigned char: fn##_uc, \
short: fn##_us, \
unsigned short: fn##_us, \
int: fn##_ui, \
unsigned int: fn##_ui, \
long: fn##_ul, \
unsigned long: fn##_ul, \
long long: fn##_ull, \
unsigned long long: fn##_ull)(x)
#define stdc_leading_zeros(x) VLIBC_STDBIT_DISPATCH(stdc_leading_zeros, x)
#define stdc_leading_ones(x) VLIBC_STDBIT_DISPATCH(stdc_leading_ones, x)
#define stdc_trailing_zeros(x) VLIBC_STDBIT_DISPATCH(stdc_trailing_zeros, x)
#define stdc_trailing_ones(x) VLIBC_STDBIT_DISPATCH(stdc_trailing_ones, x)
#define stdc_first_leading_zero(x) VLIBC_STDBIT_DISPATCH(stdc_first_leading_zero, x)
#define stdc_first_leading_one(x) VLIBC_STDBIT_DISPATCH(stdc_first_leading_one, x)
#define stdc_first_trailing_zero(x) VLIBC_STDBIT_DISPATCH(stdc_first_trailing_zero, x)
#define stdc_first_trailing_one(x) VLIBC_STDBIT_DISPATCH(stdc_first_trailing_one, x)
#define stdc_count_zeros(x) VLIBC_STDBIT_DISPATCH(stdc_count_zeros, x)
#define stdc_count_ones(x) VLIBC_STDBIT_DISPATCH(stdc_count_ones, x)
#define stdc_has_single_bit(x) VLIBC_STDBIT_DISPATCH(stdc_has_single_bit, x)
#define stdc_bit_width(x) VLIBC_STDBIT_DISPATCH(stdc_bit_width, x)
#define stdc_bit_floor(x) VLIBC_STDBIT_DISPATCH(stdc_bit_floor, x)
#define stdc_bit_ceil(x) VLIBC_STDBIT_DISPATCH(stdc_bit_ceil, x)
#endif /* VLIBC_STDBIT_H */
+27
View File
@@ -0,0 +1,27 @@
#ifndef VLIBC_STDBOOL_H
#define VLIBC_STDBOOL_H
/*
* vlibc — <stdbool.h>.
*
* In C23 bool, true and false are keywords, so this header defines only the
* guard macro __bool_true_false_are_defined. In C17 (and older) it defines
* the _Bool-based spellings the standard requires. In C++ the three names are
* keywords as well, so only the guard macro is defined there too.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
#ifndef __cplusplus
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 202311L
#define bool _Bool
#define true 1
#define false 0
#endif
#endif
#define __bool_true_false_are_defined 1
#endif /* VLIBC_STDBOOL_H */
+23
View File
@@ -0,0 +1,23 @@
#ifndef VLIBC_STDCKDINT_H
#define VLIBC_STDCKDINT_H
/*
* vlibc — <stdckdint.h>.
*
* Checked integer arithmetic (C23). Each macro computes the operation and
* stores the result through *result; it returns true when the mathematical
* result is not representable in the result type, in which case *result is
* left unmodified. The implementation defers to the GCC
* __builtin_*_overflow family, which is type-generic across every integer
* type, matching the standard's semantics.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
#define ckd_add(result, a, b) __builtin_add_overflow((a), (b), (result))
#define ckd_sub(result, a, b) __builtin_sub_overflow((a), (b), (result))
#define ckd_mul(result, a, b) __builtin_mul_overflow((a), (b), (result))
#endif /* VLIBC_STDCKDINT_H */
+11 -2
View File
@@ -20,11 +20,15 @@ typedef __SIZE_TYPE__ size_t;
/* Signed integer type of the difference of two pointers. */
typedef __PTRDIFF_TYPE__ ptrdiff_t;
/* Wide character type. */
/* Wide character type; a C++ keyword there, so no redefinition. */
#ifndef __cplusplus
typedef __WCHAR_TYPE__ wchar_t;
#endif
/* Type of the null pointer constant nullptr (C23). */
/* Type of the null pointer constant nullptr (C23); a C++ keyword there. */
#if !defined(__cplusplus) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
typedef typeof(nullptr) nullptr_t;
#endif
/* Null pointer constant. */
#define NULL ((void *)0)
@@ -32,6 +36,11 @@ typedef typeof(nullptr) nullptr_t;
/* Offset in bytes of a member from the start of its enclosing object. */
#define offsetof(type, m) __builtin_offsetof(type, m)
/* Mark the following point of the program as unreachable (C23). */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
#define unreachable() __builtin_unreachable()
#endif
/*
* An object type whose alignment is as great as that of any supported
* fundamental type; suitable as the storage type for aligned allocation.
+157
View File
@@ -0,0 +1,157 @@
#ifndef VLIBC_STDINT_H
#define VLIBC_STDINT_H
/*
* vlibc — <stdint.h>.
*
* Fixed-width integer types and their limit and constant macros (C23). Every
* definition is derived from compiler predefined macros (__INT8_TYPE__,
* __INT64_MAX__, __INT64_C, ...), so this header is fully self-contained and
* never borrows from a system header. Widths follow the x86_64 LP64 model.
*
* The compatibility profile is exposed by include/vlibc/features.h; this
* header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
/* Exact-width types. */
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
/* Types with at least the given width (least-width). */
typedef __INT_LEAST8_TYPE__ int_least8_t;
typedef __INT_LEAST16_TYPE__ int_least16_t;
typedef __INT_LEAST32_TYPE__ int_least32_t;
typedef __INT_LEAST64_TYPE__ int_least64_t;
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
/* Fastest types with at least the given width. */
typedef __INT_FAST8_TYPE__ int_fast8_t;
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
/* Types wide enough for pointers. */
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
/* Types of maximum width. */
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
/* Limits of the exact-width types. */
#define INT8_MIN (-__INT8_MAX__ - 1)
#define INT8_MAX __INT8_MAX__
#define UINT8_MAX __UINT8_MAX__
#define INT16_MIN (-__INT16_MAX__ - 1)
#define INT16_MAX __INT16_MAX__
#define UINT16_MAX __UINT16_MAX__
#define INT32_MIN (-__INT32_MAX__ - 1)
#define INT32_MAX __INT32_MAX__
#define UINT32_MAX __UINT32_MAX__
#define INT64_MIN (-__INT64_MAX__ - 1)
#define INT64_MAX __INT64_MAX__
#define UINT64_MAX __UINT64_MAX__
/* Limits of the least-width types. */
#define INT_LEAST8_MIN (-__INT_LEAST8_MAX__ - 1)
#define INT_LEAST8_MAX __INT_LEAST8_MAX__
#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
#define INT_LEAST16_MIN (-__INT_LEAST16_MAX__ - 1)
#define INT_LEAST16_MAX __INT_LEAST16_MAX__
#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
#define INT_LEAST32_MIN (-__INT_LEAST32_MAX__ - 1)
#define INT_LEAST32_MAX __INT_LEAST32_MAX__
#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
#define INT_LEAST64_MIN (-__INT_LEAST64_MAX__ - 1)
#define INT_LEAST64_MAX __INT_LEAST64_MAX__
#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
/* Limits of the fastest types. */
#define INT_FAST8_MIN (-__INT_FAST8_MAX__ - 1)
#define INT_FAST8_MAX __INT_FAST8_MAX__
#define UINT_FAST8_MAX __UINT_FAST8_MAX__
#define INT_FAST16_MIN (-__INT_FAST16_MAX__ - 1)
#define INT_FAST16_MAX __INT_FAST16_MAX__
#define UINT_FAST16_MAX __UINT_FAST16_MAX__
#define INT_FAST32_MIN (-__INT_FAST32_MAX__ - 1)
#define INT_FAST32_MAX __INT_FAST32_MAX__
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
#define INT_FAST64_MIN (-__INT_FAST64_MAX__ - 1)
#define INT_FAST64_MAX __INT_FAST64_MAX__
#define UINT_FAST64_MAX __UINT_FAST64_MAX__
/* Limits of the pointer-width and maximum-width types. */
#define INTPTR_MIN (-__INTPTR_MAX__ - 1)
#define INTPTR_MAX __INTPTR_MAX__
#define UINTPTR_MAX __UINTPTR_MAX__
#define INTMAX_MIN (-__INTMAX_MAX__ - 1)
#define INTMAX_MAX __INTMAX_MAX__
#define UINTMAX_MAX __UINTMAX_MAX__
/* Limits of other standard integer types (x86_64: wchar_t is signed int). */
#define WCHAR_MIN __WCHAR_MIN__
#define WCHAR_MAX __WCHAR_MAX__
/* Macros for integer constants of the given type. */
#define INT8_C(c) __INT8_C(c)
#define INT16_C(c) __INT16_C(c)
#define INT32_C(c) __INT32_C(c)
#define INT64_C(c) __INT64_C(c)
#define UINT8_C(c) __UINT8_C(c)
#define UINT16_C(c) __UINT16_C(c)
#define UINT32_C(c) __UINT32_C(c)
#define UINT64_C(c) __UINT64_C(c)
#define INTMAX_C(c) __INTMAX_C(c)
#define UINTMAX_C(c) __UINTMAX_C(c)
/* Width of each integer type, in bits (C23). */
#define INT8_WIDTH 8
#define INT16_WIDTH 16
#define INT32_WIDTH 32
#define INT64_WIDTH 64
#define UINT8_WIDTH 8
#define UINT16_WIDTH 16
#define UINT32_WIDTH 32
#define UINT64_WIDTH 64
#define INT_LEAST8_WIDTH __INT_LEAST8_WIDTH__
#define INT_LEAST16_WIDTH __INT_LEAST16_WIDTH__
#define INT_LEAST32_WIDTH __INT_LEAST32_WIDTH__
#define INT_LEAST64_WIDTH __INT_LEAST64_WIDTH__
#define UINT_LEAST8_WIDTH __UINT_LEAST8_WIDTH__
#define UINT_LEAST16_WIDTH __UINT_LEAST16_WIDTH__
#define UINT_LEAST32_WIDTH __UINT_LEAST32_WIDTH__
#define UINT_LEAST64_WIDTH __UINT_LEAST64_WIDTH__
#define INT_FAST8_WIDTH __INT_FAST8_WIDTH__
#define INT_FAST16_WIDTH __INT_FAST16_WIDTH__
#define INT_FAST32_WIDTH __INT_FAST32_WIDTH__
#define INT_FAST64_WIDTH __INT_FAST64_WIDTH__
#define UINT_FAST8_WIDTH __UINT_FAST8_WIDTH__
#define UINT_FAST16_WIDTH __UINT_FAST16_WIDTH__
#define UINT_FAST32_WIDTH __UINT_FAST32_WIDTH__
#define UINT_FAST64_WIDTH __UINT_FAST64_WIDTH__
#define INTPTR_WIDTH __INTPTR_WIDTH__
#define UINTPTR_WIDTH __UINTPTR_WIDTH__
#define INTMAX_WIDTH __INTMAX_WIDTH__
#define UINTMAX_WIDTH __UINTMAX_WIDTH__
#define PTRDIFF_WIDTH __PTRDIFF_WIDTH__
#define SIG_ATOMIC_WIDTH __SIG_ATOMIC_WIDTH__
#define SIZE_WIDTH __SIZE_WIDTH__
#define WCHAR_WIDTH __WCHAR_WIDTH__
#define WINT_WIDTH __WINT_WIDTH__
#endif /* VLIBC_STDINT_H */
+23
View File
@@ -0,0 +1,23 @@
#ifndef VLIBC_STDNORETURN_H
#define VLIBC_STDNORETURN_H
/*
* vlibc — <stdnoreturn.h>.
*
* In C23 noreturn is a keyword, so this header has nothing left to define.
* In C17 (and older) it maps noreturn onto the _Noreturn function specifier.
* In C++ [[noreturn]] is an attribute, not a macro, so nothing is defined
* there either.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
#ifndef __cplusplus
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 202311L
#define noreturn _Noreturn
#endif
#endif
#endif /* VLIBC_STDNORETURN_H */
+77
View File
@@ -0,0 +1,77 @@
#ifndef VLIBC_SYS_TYPES_H
#define VLIBC_SYS_TYPES_H
/*
* vlibc — <sys/types.h>.
*
* The POSIX base scalar types. This public header is authoritative for
* public consumers; src/internal/types.h mirrors the same x86_64 LP64
* choices for internal use (both agree today — see the learnings note).
* Widths follow the Linux x86_64 ABI, not the ISO minimums: long is 64-bit.
*/
#include <vlibc/features.h>
#include <stddef.h>
#if VLIBC_HAS_HEADER_SYS_TYPES_H
/* Signed type for byte counts and read()/write() results (x86_64: long). */
typedef __PTRDIFF_TYPE__ ssize_t;
/* Calendar time in seconds. */
typedef long time_t;
/* Clock ticks (times(2)). */
typedef long clock_t;
/* Clock id (clock_gettime(2)). */
typedef int clockid_t;
/* Timer id (timer_create(2)). */
typedef void *timer_t;
/* Process ID. */
typedef int pid_t;
/* User and group IDs. */
typedef unsigned int uid_t;
typedef unsigned int gid_t;
/* General identifier. */
typedef unsigned int id_t;
/* System V IPC key. */
typedef int key_t;
/* File offset. */
typedef long off_t;
/* File mode bits (and permissions). */
typedef unsigned int mode_t;
/* Device and inode numbers. */
typedef unsigned long long dev_t;
typedef unsigned long long ino_t;
/* Hard link count. */
typedef unsigned long long nlink_t;
/* Block counts and sizes. */
typedef long blkcnt_t;
typedef long blksize_t;
/* File-system block and file counts (statvfs). */
typedef unsigned long fsblkcnt_t;
typedef unsigned long fsfilcnt_t;
/* Microsecond intervals (timeval). */
typedef long suseconds_t;
typedef unsigned int useconds_t;
/* Socket address lengths. */
typedef unsigned int socklen_t;
#endif /* VLIBC_HAS_HEADER_SYS_TYPES_H */
#endif /* VLIBC_SYS_TYPES_H */
+51
View File
@@ -0,0 +1,51 @@
#ifndef VLIBC_TAR_H
#define VLIBC_TAR_H
/*
* vlibc — <tar.h>.
*
* Constants for the ustar tar archive format (POSIX). Constants only: the
* header magic and version strings, the typeflag characters that identify
* entry kinds, and the mode bits stored in each header.
*/
#include <vlibc/features.h>
#if VLIBC_HAS_HEADER_TAR_H
/* Header magic (6 bytes) and version (2 bytes). */
#define TMAGIC "ustar"
#define TMAGLEN 6
#define TVERSION "00"
#define TVERSLEN 2
/* Typeflag characters naming the entry kind. */
#define REGTYPE '0'
#define AREGTYPE '\0'
#define LNKTYPE '1'
#define SYMTYPE '2'
#define CHRTYPE '3'
#define BLKTYPE '4'
#define DIRTYPE '5'
#define FIFOTYPE '6'
#define CONTTYPE '7'
/* Set-id and sticky bits. */
#define TSUID 04000
#define TSGID 02000
#define TSVTX 01000
/* Mode bits (permissions): user, group, other. */
#define TUREAD 00400
#define TUWRITE 00200
#define TUEXEC 00100
#define TGREAD 00040
#define TGWRITE 00020
#define TGEXEC 00010
#define TOREAD 00004
#define TOWRITE 00002
#define TOEXEC 00001
#endif /* VLIBC_HAS_HEADER_TAR_H */
#endif /* VLIBC_TAR_H */
+18
View File
@@ -0,0 +1,18 @@
#ifndef VLIBC_TGMATH_H
#define VLIBC_TGMATH_H
/*
* vlibc — <tgmath.h>.
*
* Type-generic math. STUB: the type-generic dispatch over <math.h> is
* IMPLEMENTED by the first math todo (#39), not here. This stub exists so
* that including <tgmath.h> alongside the other headers compiles cleanly
* today; it deliberately defines no type-generic macros until #39 lands
* the <math.h> function inventory it dispatches to.
*
* This header is ISO C core and is present in every profile.
*/
#include <vlibc/features.h>
#endif /* VLIBC_TGMATH_H */
+190
View File
@@ -0,0 +1,190 @@
#ifndef VLIBC_THREADS_H
#define VLIBC_THREADS_H
/*
* vlibc — <threads.h>.
*
* C11 threads. STUB: the header lands here (level-1 gate) but every
* function is implemented by the threads todo (#45), which wraps them as
* thin aliases over the pthread layer. Until then, user code compiles
* against these declarations and linking resolves once #45 lands.
*
* The types are placeholder shapes for now; #45 owns their final form (the
* pthread-backed layout) and may refine them in place.
*/
#include <vlibc/features.h>
#if VLIBC_HAS_HEADER_THREADS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Forward-declared: the real definition lives in <time.h> (later todo). */
struct timespec;
/* Thread identifier (x86_64: matches pthread_t's unsigned long). */
typedef unsigned long thrd_t;
/* Start routine of a thread. */
typedef int (*thrd_start_t)(void *);
/* Destructor run when a thread exits. */
typedef void (*tss_dtor_t)(void *);
/* Mutex. */
typedef struct
{
unsigned long opaque;
} mtx_t;
/* Condition variable. */
typedef struct
{
unsigned long opaque;
} cnd_t;
/* Thread-specific storage key. */
typedef struct
{
unsigned long opaque;
} tss_t;
/* call_once state. */
typedef struct
{
unsigned long opaque;
} once_flag;
/* Initializer for a once_flag object. */
#define ONCE_FLAG_INIT {0}
/* Upper bound on tss_dtor_t invocations per key at thread exit. */
#define TSS_DTOR_ITERATIONS 4
/* Mutex kinds for mtx_init. */
enum
{
mtx_plain = 0,
mtx_recursive = 1,
mtx_timed = 2
};
/* Result codes shared by the thrd_* and mtx_* functions. */
enum
{
thrd_success = 0,
thrd_busy = 1,
thrd_error = 2,
thrd_nomem = 3,
thrd_timedout = 4
};
/* Create a thread running func(arg); stores its id through thr. */
int
thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
/* Non-zero iff lhs and rhs name the same thread. */
int
thrd_equal(thrd_t lhs, thrd_t rhs);
/* Identifier of the calling thread. */
thrd_t
thrd_current(void);
/* Sleep for the interval in *duration; *remaining gets the unslept part. */
int
thrd_sleep(const struct timespec *duration, struct timespec *remaining);
/* Yield the processor to other runnable threads. */
void
thrd_yield(void);
/* Terminate the calling thread, reporting res. */
_Noreturn void
thrd_exit(int res);
/* Detach thr so its resources are released on exit. */
int
thrd_detach(thrd_t thr);
/* Wait for thr to exit; stores its result through *res when non-NULL. */
int
thrd_join(thrd_t thr, int *res);
/* Initialize *mtx with the given kind. */
int
mtx_init(mtx_t *mtx, int type);
/* Lock *mtx, blocking if needed. */
int
mtx_lock(mtx_t *mtx);
/* Lock *mtx, blocking at most until *ts. */
int
mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts);
/* Lock *mtx unless another thread holds it (thrd_busy). */
int
mtx_trylock(mtx_t *mtx);
/* Unlock *mtx. */
int
mtx_unlock(mtx_t *mtx);
/* Release *mtx's resources. */
void
mtx_destroy(mtx_t *mtx);
/* Run func exactly once per once_flag object. */
void
call_once(once_flag *flag, void (*func)(void));
/* Initialize *cnd. */
int
cnd_init(cnd_t *cnd);
/* Wake one thread waiting on *cnd. */
int
cnd_signal(cnd_t *cnd);
/* Wake all threads waiting on *cnd. */
int
cnd_broadcast(cnd_t *cnd);
/* Wait on *cnd; *mtx must be locked by the caller. */
int
cnd_wait(cnd_t *cnd, mtx_t *mtx);
/* Wait on *cnd at most until *ts. */
int
cnd_timedwait(cnd_t *restrict cnd, mtx_t *restrict mtx, const struct timespec *restrict ts);
/* Release *cnd's resources. */
void
cnd_destroy(cnd_t *cnd);
/* Create a thread-specific key *key; dtor may be NULL. */
int
tss_create(tss_t *key, tss_dtor_t dtor);
/* Value stored for *key in the calling thread (NULL when unset). */
void *
tss_get(tss_t key);
/* Store val under *key for the calling thread. */
int
tss_set(tss_t key, void *val);
/* Release *key; the key may not be used afterwards. */
void
tss_delete(tss_t key);
#ifdef __cplusplus
}
#endif
#endif /* VLIBC_HAS_HEADER_THREADS_H */
#endif /* VLIBC_THREADS_H */
+64
View File
@@ -0,0 +1,64 @@
#ifndef VLIBC_UCHAR_H
#define VLIBC_UCHAR_H
/*
* vlibc — <uchar.h>.
*
* Unicode character types and the multibyte conversion declarations (C11,
* gated at level 1 per the plan's header inventory). In C23 char16_t and
* char32_t are keywords, so the typedefs below only fire in C17 (and
* older); the C17 types are the compiler's __CHAR16_TYPE__/__CHAR32_TYPE__,
* which is what the C23 keywords name as well.
*
* The mbrtoc16/mbrtoc32/c16rtomb/c32rtomb functions are DECLARED here but
* implemented by the multibyte todo (#50): user code compiles against this
* header today and linking resolves once #50 lands.
*/
#include <vlibc/features.h>
#include <stddef.h>
#if VLIBC_HAS_HEADER_UCHAR_H
/*
* char16_t/char32_t remain typedefs in C23 (unlike bool/alignas/... they were
* NOT promoted to keywords), so they are defined in every C mode from the
* compiler's __CHAR16_TYPE__/__CHAR32_TYPE__; in C++ they are keywords and
* no typedef fires.
*/
#ifndef __cplusplus
typedef __CHAR16_TYPE__ char16_t;
typedef __CHAR32_TYPE__ char32_t;
#endif
/*
* Conversion state for multibyte conversions. Two opaque words; the real
* layout is owned by the multibyte todo (#50), which may extend this
* definition when it lands (see the learnings note).
*/
typedef struct
{
unsigned int state[2];
} mbstate_t;
/*
* Multibyte <-> UTF-16/UTF-32 conversions (implemented in #50).
*
* mbrtoc16: convert at most n bytes of the multibyte string s to a char16_t
* stored through pc16, consuming the corresponding number of bytes.
* c16rtomb: convert char16_t c16 to at most MB_CUR_MAX bytes at s.
* The char32_t forms are the same for UTF-32.
*/
size_t
mbrtoc16(char16_t *restrict pc16, const char *restrict s, size_t n, mbstate_t *restrict ps);
size_t
c16rtomb(char *restrict s, char16_t c16, mbstate_t *restrict ps);
size_t
mbrtoc32(char32_t *restrict pc32, const char *restrict s, size_t n, mbstate_t *restrict ps);
size_t
c32rtomb(char *restrict s, char32_t c32, mbstate_t *restrict ps);
#endif /* VLIBC_HAS_HEADER_UCHAR_H */
#endif /* VLIBC_UCHAR_H */
+17
View File
@@ -57,4 +57,21 @@
#define VLIBC_HAS_VLIBC 1
#endif
/*
* Per-header availability gates, derived from VLIBC_LEVEL. The ISO C core
* headers (<stddef.h>, <stdint.h>, <stdbool.h>, <stdalign.h>, <iso646.h>,
* <limits.h>, <float.h>, <assert.h>, <stdarg.h>, <stdnoreturn.h>,
* <stdatomic.h>, <stdbit.h>, <stdckdint.h>, <tgmath.h>) are present in every
* profile and carry no gate. The POSIX-facing headers below exist only in
* profiles that provide POSIX (level >= 1, i.e. all profiles today); each
* header includes this file and gates its declarations on its own macro.
*/
#if VLIBC_LEVEL >= 1
#define VLIBC_HAS_HEADER_SYS_TYPES_H 1
#define VLIBC_HAS_HEADER_UCHAR_H 1
#define VLIBC_HAS_HEADER_CPIO_H 1
#define VLIBC_HAS_HEADER_TAR_H 1
#define VLIBC_HAS_HEADER_THREADS_H 1
#endif
#endif /* VLIBC_FEATURES_H */