Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <[email protected]>
112 lines
3.8 KiB
Markdown
112 lines
3.8 KiB
Markdown
# 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.
|