3.8 KiB
3.8 KiB
fastwc Style Guide
The style is the law. GNU wc can afford to look like a committee designed it — it was. We're one file, one purpose, one opinion.
The language
- C99 with POSIX.
_POSIX_C_SOURCE 200809L. We target the standard, not a compiler vendor's mood. - Zero warnings with
-Wall -Wextra. A warning is a bug you haven't fixed yet. Fix it. - No compiler-specific extensions unless they're guarded and the
benchmark gets faster because of it.
__builtin_popcountllis the one exception — it's the price of admission on every compiler that matters, and the benchmark proves it.
Format
- 4 spaces. Not tabs, not 8 spaces. GNU uses tabs because GNU was written in 1985 by people who had strong opinions about typewriters.
- 80 columns. If your line is longer, your idea is longer than it needs to be.
- Braces on the next line (Allman). Everywhere. Functions, blocks, switch cases. Consistency is the only religion here, and we're devout.
- Snake case for everything.
count_stream,ws_tab,nread. No CamelCase — that's for languages that need help knowing what a word is.
Structure
- One file:
src/main.c. See CONTRIBUTING.md rule 6. This is not a suggestion. - Everything is
static. The binary exports nothing. We're not a library, we're a verdict. - Types end in
_t.counts_t, and not much else. GNU has a type for everything and a committee to name it. We have counts, and we count. - No globals except what's truly process-wide.
flagsandws_tablive at file scope because they're the program's identity. Everything else gets passed around like it's hot.
The hot path
count_stream(), count_newlines(), count_words() are the product.
The rest of the file is just the packaging.
- Fixed stride. No per-token function calls. No
isspace()in a loop — that's what the lookup table is for. - No allocation, no locks, no syscalls in the counting loop. The
freadis the only syscall, and it's not yours to add to. - Branchless where it costs nothing. A predictable branch is fine; a mispredicted one is a lie you told the CPU.
- The buffer is
static, 128 KiB, and never grows. GNU's wc reads in chunks too — ours just doesn't make a ceremony of it.
Counts
long longfor everything that counts. Files can be bigger than your opinions. Signed, because overflow should scream, not wrap.- Lines are
'\n's. Not "lines of text," not "records." A file without a trailing newline has fewer newlines than it has lines, and that's correct. GNU agrees with us on this one, so it must be right. - Words are whitespace-delimited runs. The lookup table decides what whitespace is; the popcount decides how many words; you don't get an opinion.
Errors
fastwc: <file>: <message>on stderr, and keep going. GNU wc fails gracefully across multiple files, and we'll credit them that one thing. Then we'll be faster at it.- Exit 1 if anything failed, 0 otherwise. No drama, no
EXIT_FAILUREpoetry.
Comments
- Only when the code can't speak for itself. The SWAR newline
counter in
count_newlines()gets a comment because(x ^ nl) & clis a sentence in a language you don't speak yet.i++does not get a comment. - No commented-out code. The dead don't get to live in the file.
- No TODO without a date. A TODO without a date is a promise you plan to break.
What the style is not
- It is not GNU's style. GNU's style was written by a committee, ratified by a foundation, and translated into fourteen languages.
- It is not "whatever your editor defaults to." Your editor has opinions. So do we. Ours are right.
- It is not negotiable in review. If a PR violates the style, the PR is a rewrite request with extra steps.