# Styleguide This file is the source of truth for how vlibc code looks. `.clang-format` is generated from / kept in sync with it. ## Language - C23 is the default standard; C2y (C29) is opt-in via `--enable-c29`. - GCC only. Compiler extensions (`__attribute__`, statement expressions, `defer` under C2y) are permitted and encouraged where they improve clarity or performance. ## Formatting - 4-space indent, no tabs. - 100-column limit. - Allman braces: opening brace on its own line, for functions and blocks. - Always use braces, even for single-statement blocks (avoids `goto fail`-style bugs and matches `.clang-tidy`). - Pointer and qualifier attach to the name: `const char *s`, `int *p`. - Spaces around binary operators; no space after unary operators. The one exception to Allman braces is the C++ linkage guard: `extern "C" {` keeps its opening brace attached (encoded as `AfterExternBlock: false` in `.clang-format`), because that is the idiomatic form every C header uses. ```c int foo(const char *s, size_t n) { if (n == 0) { return 0; } return (int)(s[0] == 'x'); } ``` ## Naming - Functions and variables: `snake_case`. - Types: `snake_case` (struct tags); typedefs avoid the POSIX-reserved `_t` suffix. - Macros and constants: `UPPER_SNAKE_CASE`. - Public identifiers are prefixed `vlibc_` to avoid collisions. - Identifiers beginning with `_` (or `__`, or `_[A-Z]`) are reserved for the implementation and the C/POSIX standards — do not introduce new ones. ## Include guards Public headers use traditional include guards: ```c #ifndef VLIBC_H #define VLIBC_H ... #endif /* VLIBC_H */ ``` `#pragma once` is a widely supported extension but is deliberately not used: it relies on compiler-specific path canonicalization and can mis-deduplicate headers reachable through symlinks or bind mounts. For a libc whose headers are consumed in many toolchain configurations, explicit guards are the robust default. ## Compiler intent Public declarations annotate *intent* so the compiler can optimize statically linked binaries (see `docs/overview.md`): - `__attribute__((const))` — result depends only on arguments. - `__attribute__((pure))` — no side effects; may read memory. - `__attribute__((always_inline))`, `__attribute__((leaf))`, `__attribute__((malloc))`, `__attribute__((access, ...))` — as appropriate. Every public function carries the tightest correct attribute. ## Profile gating Profile-gated code follows these formatting and naming conventions (the semantic classification of functions into levels lives in `docs/compatibility.md`, not here): - Public headers gate declarations with `#if VLIBC_LEVEL >= N`. Prefer the `VLIBC_LEVEL_GE(n)` helper from `include/vlibc/features.h`; fall back to the raw comparison only when the level is a literal constant: ```c #if VLIBC_LEVEL_GE(2) size_t strlcpy(char *dst, const char *src, size_t n); #endif ``` - Group implementation sources by level in `Makefile.am` using the per-level conditionals `if PROFILE_GE_2` / `if PROFILE_GE_3`, mirroring the `#if VLIBC_LEVEL >= N` rule in headers. - Standard headers use `VLIBC_`-prefixed include guards (`VLIBC_STDDEF_H`, `VLIBC_STRING_H`), never the `_STDDEF_H`-style reserved forms. A leading underscore is reserved for the implementation and the C/POSIX standards (see Naming); the `VLIBC_` prefix stays out of the reserved namespace while remaining unambiguous. - Intent attributes respect the gating: `pure` / `const` are only valid on side-effect-free functions. Never annotate a mutating function (`memcpy`, `memmove`, `memset`, `strlcpy`, `strlcat`) with either. ## Error handling - No empty blocks; no silent failure. - Library functions return errors via return codes or `errno`; they never terminate the caller's process.