red64-cli 0.3.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +194 -338
- package/dist/cli/parseArgs.d.ts.map +1 -1
- package/dist/cli/parseArgs.js +5 -13
- package/dist/cli/parseArgs.js.map +1 -1
- package/dist/components/init/types.d.ts +0 -2
- package/dist/components/init/types.d.ts.map +1 -1
- package/dist/components/screens/HelpScreen.d.ts.map +1 -1
- package/dist/components/screens/HelpScreen.js +0 -2
- package/dist/components/screens/HelpScreen.js.map +1 -1
- package/dist/components/screens/InitScreen.d.ts.map +1 -1
- package/dist/components/screens/InitScreen.js +5 -8
- package/dist/components/screens/InitScreen.js.map +1 -1
- package/dist/components/screens/StartScreen.d.ts.map +1 -1
- package/dist/components/screens/StartScreen.js +29 -8
- package/dist/components/screens/StartScreen.js.map +1 -1
- package/dist/components/screens/StatusScreen.d.ts.map +1 -1
- package/dist/components/screens/StatusScreen.js +16 -1
- package/dist/components/screens/StatusScreen.js.map +1 -1
- package/dist/services/AgentInvoker.d.ts.map +1 -1
- package/dist/services/AgentInvoker.js +76 -37
- package/dist/services/AgentInvoker.js.map +1 -1
- package/dist/services/ClaudeErrorDetector.d.ts +1 -1
- package/dist/services/ClaudeErrorDetector.d.ts.map +1 -1
- package/dist/services/ClaudeErrorDetector.js +1 -0
- package/dist/services/ClaudeErrorDetector.js.map +1 -1
- package/dist/services/ClaudeHealthCheck.d.ts +7 -0
- package/dist/services/ClaudeHealthCheck.d.ts.map +1 -1
- package/dist/services/ClaudeHealthCheck.js +76 -12
- package/dist/services/ClaudeHealthCheck.js.map +1 -1
- package/dist/services/ConfigService.d.ts +1 -0
- package/dist/services/ConfigService.d.ts.map +1 -1
- package/dist/services/ConfigService.js.map +1 -1
- package/dist/services/DockerRunner.js +1 -1
- package/dist/services/DockerRunner.js.map +1 -1
- package/dist/services/PhaseExecutor.d.ts.map +1 -1
- package/dist/services/PhaseExecutor.js +2 -1
- package/dist/services/PhaseExecutor.js.map +1 -1
- package/dist/services/TaskRunner.d.ts.map +1 -1
- package/dist/services/TaskRunner.js +2 -1
- package/dist/services/TaskRunner.js.map +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/index.js.map +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/framework/stacks/c/code-quality.md +326 -0
- package/framework/stacks/c/coding-style.md +347 -0
- package/framework/stacks/c/conventions.md +513 -0
- package/framework/stacks/c/error-handling.md +350 -0
- package/framework/stacks/c/feedback.md +158 -0
- package/framework/stacks/c/memory-safety.md +408 -0
- package/framework/stacks/c/tech.md +122 -0
- package/framework/stacks/c/testing.md +472 -0
- package/framework/stacks/cpp/code-quality.md +282 -0
- package/framework/stacks/cpp/coding-style.md +363 -0
- package/framework/stacks/cpp/conventions.md +420 -0
- package/framework/stacks/cpp/error-handling.md +264 -0
- package/framework/stacks/cpp/feedback.md +104 -0
- package/framework/stacks/cpp/memory-safety.md +351 -0
- package/framework/stacks/cpp/tech.md +160 -0
- package/framework/stacks/cpp/testing.md +323 -0
- package/framework/stacks/java/code-quality.md +357 -0
- package/framework/stacks/java/coding-style.md +400 -0
- package/framework/stacks/java/conventions.md +437 -0
- package/framework/stacks/java/error-handling.md +408 -0
- package/framework/stacks/java/feedback.md +180 -0
- package/framework/stacks/java/tech.md +126 -0
- package/framework/stacks/java/testing.md +485 -0
- package/framework/stacks/javascript/async-patterns.md +216 -0
- package/framework/stacks/javascript/code-quality.md +182 -0
- package/framework/stacks/javascript/coding-style.md +293 -0
- package/framework/stacks/javascript/conventions.md +268 -0
- package/framework/stacks/javascript/error-handling.md +216 -0
- package/framework/stacks/javascript/feedback.md +80 -0
- package/framework/stacks/javascript/tech.md +114 -0
- package/framework/stacks/javascript/testing.md +209 -0
- package/framework/stacks/loco/code-quality.md +156 -0
- package/framework/stacks/loco/coding-style.md +247 -0
- package/framework/stacks/loco/error-handling.md +225 -0
- package/framework/stacks/loco/feedback.md +35 -0
- package/framework/stacks/loco/loco.md +342 -0
- package/framework/stacks/loco/structure.md +193 -0
- package/framework/stacks/loco/tech.md +129 -0
- package/framework/stacks/loco/testing.md +211 -0
- package/framework/stacks/rust/code-quality.md +370 -0
- package/framework/stacks/rust/coding-style.md +475 -0
- package/framework/stacks/rust/conventions.md +430 -0
- package/framework/stacks/rust/error-handling.md +399 -0
- package/framework/stacks/rust/feedback.md +152 -0
- package/framework/stacks/rust/memory-safety.md +398 -0
- package/framework/stacks/rust/tech.md +121 -0
- package/framework/stacks/rust/testing.md +528 -0
- package/package.json +14 -2
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# Code Quality Standards
|
|
2
|
+
|
|
3
|
+
Project memory for code quality conventions: formatting, static analysis, sanitizers, and compiler warnings in modern C.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
- **Shift left**: Catch bugs at compile time, not runtime
|
|
10
|
+
- **Automate enforcement**: clang-format and clang-tidy in CI, not code review
|
|
11
|
+
- **Warnings are errors**: `-Werror` in CI ensures nothing slips through
|
|
12
|
+
- **Sanitizers in test**: Run ASan/UBSan on every test run in CI
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## clang-format Configuration
|
|
17
|
+
|
|
18
|
+
### `.clang-format`
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
BasedOnStyle: LLVM
|
|
22
|
+
Language: Cpp
|
|
23
|
+
Standard: c17
|
|
24
|
+
ColumnLimit: 100
|
|
25
|
+
IndentWidth: 4
|
|
26
|
+
UseTab: Never
|
|
27
|
+
BreakBeforeBraces: Attach
|
|
28
|
+
AllowShortFunctionsOnASingleLine: Empty
|
|
29
|
+
AllowShortIfStatementsOnASingleLine: Never
|
|
30
|
+
AllowShortLoopsOnASingleLine: false
|
|
31
|
+
PointerAlignment: Right
|
|
32
|
+
SpaceBeforeParens: ControlStatements
|
|
33
|
+
SortIncludes: CaseSensitive
|
|
34
|
+
IncludeBlocks: Regroup
|
|
35
|
+
IncludeCategories:
|
|
36
|
+
- Regex: '^".*"' # Project headers (corresponding header first)
|
|
37
|
+
Priority: 1
|
|
38
|
+
- Regex: '^<(assert|ctype|errno|float|limits|locale|math|setjmp|signal|stdarg|stddef|stdio|stdlib|string|time|stdbool|stdint|inttypes|stdalign|stdatomic|stdnoreturn|threads|uchar)\.h>'
|
|
39
|
+
Priority: 2 # C standard library
|
|
40
|
+
- Regex: '^<(sys|unistd|fcntl|pthread|netinet|arpa|dlfcn).*>'
|
|
41
|
+
Priority: 3 # POSIX / system
|
|
42
|
+
- Regex: '^<.+>' # Third-party
|
|
43
|
+
Priority: 4
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Format all source files
|
|
48
|
+
clang-format -i $(find src include -name '*.c' -o -name '*.h')
|
|
49
|
+
|
|
50
|
+
# Check formatting (CI)
|
|
51
|
+
clang-format --dry-run --Werror $(find src include -name '*.c' -o -name '*.h')
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## clang-tidy Configuration
|
|
57
|
+
|
|
58
|
+
### `.clang-tidy`
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
Checks: >
|
|
62
|
+
-*,
|
|
63
|
+
bugprone-*,
|
|
64
|
+
cert-*,
|
|
65
|
+
misc-*,
|
|
66
|
+
readability-*,
|
|
67
|
+
performance-*,
|
|
68
|
+
clang-analyzer-*,
|
|
69
|
+
-readability-identifier-length,
|
|
70
|
+
-readability-magic-numbers,
|
|
71
|
+
-bugprone-easily-swappable-parameters,
|
|
72
|
+
-cert-err33-c
|
|
73
|
+
|
|
74
|
+
WarningsAsErrors: >
|
|
75
|
+
bugprone-*,
|
|
76
|
+
cert-str34-c,
|
|
77
|
+
cert-mem57-c,
|
|
78
|
+
clang-analyzer-security.*,
|
|
79
|
+
clang-analyzer-deadcode.*
|
|
80
|
+
|
|
81
|
+
CheckOptions:
|
|
82
|
+
- key: readability-identifier-naming.FunctionCase
|
|
83
|
+
value: lower_case
|
|
84
|
+
- key: readability-identifier-naming.VariableCase
|
|
85
|
+
value: lower_case
|
|
86
|
+
- key: readability-identifier-naming.MacroDefinitionCase
|
|
87
|
+
value: UPPER_CASE
|
|
88
|
+
- key: readability-identifier-naming.TypedefCase
|
|
89
|
+
value: lower_case
|
|
90
|
+
- key: readability-identifier-naming.TypedefSuffix
|
|
91
|
+
value: _t
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Key Check Categories
|
|
95
|
+
|
|
96
|
+
| Category | Purpose | Example Checks |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| `bugprone-*` | Common bug patterns | `sizeof-expression`, `narrowing-conversions`, `string-literal-with-embedded-nul` |
|
|
99
|
+
| `cert-*` | CERT C secure coding | `err34-c` (check return of `atoi`), `str34-c` (sign of `char`), `mem57-c` |
|
|
100
|
+
| `clang-analyzer-*` | Static analysis (deep) | `security.insecureAPI.strcpy`, `deadcode.DeadStores` |
|
|
101
|
+
| `performance-*` | Performance improvements | `type-promotion-in-math-fn` |
|
|
102
|
+
| `readability-*` | Code clarity | `identifier-naming`, `implicit-bool-conversion` |
|
|
103
|
+
| `misc-*` | Miscellaneous | `unused-parameters`, `redundant-expression` |
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Run clang-tidy (requires compile_commands.json)
|
|
107
|
+
run-clang-tidy -p build
|
|
108
|
+
|
|
109
|
+
# Single file
|
|
110
|
+
clang-tidy -p build src/main.c
|
|
111
|
+
|
|
112
|
+
# With auto-fix
|
|
113
|
+
run-clang-tidy -p build -fix
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## cppcheck (Supplementary)
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Run with compile database
|
|
122
|
+
cppcheck --project=build/compile_commands.json \
|
|
123
|
+
--std=c17 \
|
|
124
|
+
--enable=all \
|
|
125
|
+
--suppress=missingIncludeSystem \
|
|
126
|
+
--error-exitcode=1 \
|
|
127
|
+
--inline-suppr
|
|
128
|
+
|
|
129
|
+
# Without compile database
|
|
130
|
+
cppcheck --enable=all --std=c17 \
|
|
131
|
+
--suppress=missingInclude \
|
|
132
|
+
-I include/ \
|
|
133
|
+
src/
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### cppcheck Key Checks
|
|
137
|
+
|
|
138
|
+
| Check | What It Finds |
|
|
139
|
+
|---|---|
|
|
140
|
+
| `nullPointer` | Null pointer dereference |
|
|
141
|
+
| `memleak` | Memory not freed on all paths |
|
|
142
|
+
| `bufferAccessOutOfBounds` | Array out-of-bounds access |
|
|
143
|
+
| `uninitvar` | Use of uninitialized variable |
|
|
144
|
+
| `resourceLeak` | File handle or socket not closed |
|
|
145
|
+
| `redundantAssignment` | Variable assigned then overwritten |
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Compiler Warnings
|
|
150
|
+
|
|
151
|
+
### Recommended Flags
|
|
152
|
+
|
|
153
|
+
```cmake
|
|
154
|
+
# CMakeLists.txt
|
|
155
|
+
target_compile_options(myapp PRIVATE
|
|
156
|
+
$<$<C_COMPILER_ID:GNU,Clang,AppleClang>:
|
|
157
|
+
-Wall
|
|
158
|
+
-Wextra
|
|
159
|
+
-Wpedantic
|
|
160
|
+
-Werror
|
|
161
|
+
-Wshadow
|
|
162
|
+
-Wconversion
|
|
163
|
+
-Wsign-conversion
|
|
164
|
+
-Wdouble-promotion
|
|
165
|
+
-Wformat=2
|
|
166
|
+
-Wformat-overflow=2
|
|
167
|
+
-Wformat-truncation=2
|
|
168
|
+
-Wimplicit-fallthrough
|
|
169
|
+
-Wnull-dereference
|
|
170
|
+
-Wunused
|
|
171
|
+
-Wstrict-prototypes
|
|
172
|
+
-Wold-style-definition
|
|
173
|
+
-Wmissing-prototypes
|
|
174
|
+
-Wmissing-declarations
|
|
175
|
+
-Wcast-align
|
|
176
|
+
-Wwrite-strings
|
|
177
|
+
-Wvla
|
|
178
|
+
>
|
|
179
|
+
$<$<C_COMPILER_ID:GNU>:
|
|
180
|
+
-Wlogical-op
|
|
181
|
+
-Wduplicated-cond
|
|
182
|
+
-Wduplicated-branches
|
|
183
|
+
-Wjump-misses-init
|
|
184
|
+
>
|
|
185
|
+
)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
| Flag | Purpose |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `-Wall -Wextra` | Enable most warnings |
|
|
191
|
+
| `-Wpedantic` | Enforce strict ISO C compliance |
|
|
192
|
+
| `-Werror` | Treat warnings as errors (CI) |
|
|
193
|
+
| `-Wshadow` | Warn on variable shadowing |
|
|
194
|
+
| `-Wconversion` | Warn on implicit narrowing conversions |
|
|
195
|
+
| `-Wstrict-prototypes` | Require full prototypes (not empty parens) |
|
|
196
|
+
| `-Wmissing-prototypes` | Warn if global function has no prior prototype |
|
|
197
|
+
| `-Wvla` | Forbid variable-length arrays (stack overflow risk) |
|
|
198
|
+
| `-Wformat=2` | Extra format string checks |
|
|
199
|
+
| `-Wold-style-definition` | Forbid K&R style function definitions |
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Sanitizers
|
|
204
|
+
|
|
205
|
+
### AddressSanitizer (ASan)
|
|
206
|
+
|
|
207
|
+
Detects: buffer overflows, use-after-free, use-after-scope, double-free, memory leaks.
|
|
208
|
+
|
|
209
|
+
```cmake
|
|
210
|
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
|
211
|
+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### UndefinedBehaviorSanitizer (UBSan)
|
|
215
|
+
|
|
216
|
+
Detects: signed integer overflow, null pointer dereference, misaligned access, out-of-bounds shifts, type punning.
|
|
217
|
+
|
|
218
|
+
```cmake
|
|
219
|
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### MemorySanitizer (MSan) -- Clang Only
|
|
223
|
+
|
|
224
|
+
Detects: reads of uninitialized memory.
|
|
225
|
+
|
|
226
|
+
```cmake
|
|
227
|
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fno-omit-frame-pointer")
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### ThreadSanitizer (TSan)
|
|
231
|
+
|
|
232
|
+
Detects: data races, deadlocks.
|
|
233
|
+
|
|
234
|
+
```cmake
|
|
235
|
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread")
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Sanitizer CMake Preset Pattern
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"name": "asan",
|
|
243
|
+
"inherits": "debug",
|
|
244
|
+
"cacheVariables": {
|
|
245
|
+
"CMAKE_C_FLAGS": "-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all"
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Note**: ASan and TSan cannot be combined. Run them as separate CI jobs.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## CERT C Coding Standard References
|
|
255
|
+
|
|
256
|
+
Key CERT C rules to enforce via tooling and review:
|
|
257
|
+
|
|
258
|
+
| Rule | Description | Enforcement |
|
|
259
|
+
|---|---|---|
|
|
260
|
+
| **ERR33-C** | Detect and handle standard library errors | clang-tidy `cert-err33-c` |
|
|
261
|
+
| **STR31-C** | Guarantee null-terminated strings have sufficient space | Manual review, ASan |
|
|
262
|
+
| **MEM30-C** | Do not access freed memory | ASan, Valgrind |
|
|
263
|
+
| **MEM35-C** | Allocate sufficient memory for an object | ASan, cppcheck |
|
|
264
|
+
| **ARR38-C** | Guarantee array indices are within valid range | UBSan, ASan |
|
|
265
|
+
| **INT32-C** | Ensure signed integer operations do not overflow | UBSan |
|
|
266
|
+
| **FIO42-C** | Close files when they are no longer needed | cppcheck `resourceLeak` |
|
|
267
|
+
| **MSC24-C** | Do not use deprecated or obsolescent functions | clang-tidy, `-Wdeprecated` |
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Code Coverage
|
|
272
|
+
|
|
273
|
+
### gcov / lcov
|
|
274
|
+
|
|
275
|
+
```cmake
|
|
276
|
+
# Coverage build
|
|
277
|
+
target_compile_options(myapp_tests PRIVATE --coverage)
|
|
278
|
+
target_link_options(myapp_tests PRIVATE --coverage)
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
# Generate coverage report
|
|
283
|
+
cmake --build build-coverage
|
|
284
|
+
ctest --test-dir build-coverage
|
|
285
|
+
lcov --capture --directory build-coverage --output-file coverage.info
|
|
286
|
+
lcov --remove coverage.info '/usr/*' '*/test/*' --output-file coverage.info
|
|
287
|
+
genhtml coverage.info --output-directory coverage-report/
|
|
288
|
+
|
|
289
|
+
# Alternative: gcovr
|
|
290
|
+
gcovr --root . --html --html-details -o coverage/index.html
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Quality Commands Summary
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
# Full quality check (CI pipeline)
|
|
299
|
+
clang-format --dry-run --Werror $(find src include -name '*.c' -o -name '*.h')
|
|
300
|
+
run-clang-tidy -p build
|
|
301
|
+
cppcheck --project=build/compile_commands.json --error-exitcode=1
|
|
302
|
+
cmake --build build-asan && ctest --test-dir build-asan --output-on-failure
|
|
303
|
+
cmake --build build-coverage && ctest --test-dir build-coverage
|
|
304
|
+
|
|
305
|
+
# Development workflow
|
|
306
|
+
clang-format -i src/**/*.c include/**/*.h # Quick format
|
|
307
|
+
cmake --build build && ctest --test-dir build # Fast feedback
|
|
308
|
+
clang-tidy -p build src/my_file.c # Focused analysis
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Anti-Patterns
|
|
314
|
+
|
|
315
|
+
| Anti-Pattern | Problem | Correct Approach |
|
|
316
|
+
|---|---|---|
|
|
317
|
+
| No `-Werror` in CI | Warnings accumulate silently | `-Werror` in CI builds |
|
|
318
|
+
| Suppressing warnings globally | Hides real bugs | Suppress per-line with comments only when justified |
|
|
319
|
+
| No sanitizers in test | Memory bugs hide until production | ASan + UBSan on every CI test run |
|
|
320
|
+
| Manual code review for style | Inconsistent, wastes reviewer time | clang-format enforces automatically |
|
|
321
|
+
| No `compile_commands.json` | clang-tidy cannot find headers | `set(CMAKE_EXPORT_COMPILE_COMMANDS ON)` |
|
|
322
|
+
| Ignoring cppcheck findings | Misses bugs clang-tidy does not catch | Run both tools; they complement each other |
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
_Focus on patterns over exhaustive rules. Code should be formatted, analyzed, and tested under sanitizers before it reaches review._
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
# C Coding Style
|
|
2
|
+
|
|
3
|
+
Coding style conventions for modern C projects. Opinionated patterns for readable, maintainable C17/C23 code beyond what clang-format enforces automatically.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
- **Explicit over implicit**: C gives you control; use it deliberately and visibly
|
|
10
|
+
- **Consistency above all**: snake_case everywhere, K&R braces, predictable structure
|
|
11
|
+
- **Const correctness**: If it does not change, mark it `const`
|
|
12
|
+
- **Minimal scope**: Static for internal linkage, block-scoped variables, small functions
|
|
13
|
+
- **Automate what you can**: Let clang-format handle layout; this doc covers judgment calls
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Naming Conventions
|
|
18
|
+
|
|
19
|
+
### Standard C Naming
|
|
20
|
+
|
|
21
|
+
| Element | Convention | Example |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| Functions | `snake_case` | `parse_config`, `get_user_count` |
|
|
24
|
+
| Variables, parameters | `snake_case` | `user_count`, `max_retries` |
|
|
25
|
+
| Typedefs (structs, enums) | `snake_case_t` | `user_t`, `config_t`, `error_code_t` |
|
|
26
|
+
| Macros | `UPPER_CASE` | `MAX_BUFFER_SIZE`, `LOG_ERROR` |
|
|
27
|
+
| Constants (`#define`, `enum`) | `UPPER_CASE` | `MAX_RETRIES`, `STATUS_OK` |
|
|
28
|
+
| Enum values | `PREFIX_UPPER_CASE` | `ERR_NOT_FOUND`, `STATUS_ACTIVE` |
|
|
29
|
+
| Struct members | `snake_case` | `first_name`, `retry_count` |
|
|
30
|
+
| File-local (static) functions | `snake_case` (no prefix needed) | `validate_input` |
|
|
31
|
+
| Global variables (avoid) | `g_snake_case` | `g_config`, `g_logger` |
|
|
32
|
+
| Pointer variables | `*` attached to name | `int *ptr`, `char *name` |
|
|
33
|
+
|
|
34
|
+
### Naming Rules
|
|
35
|
+
|
|
36
|
+
```c
|
|
37
|
+
/* GOOD: Descriptive, reveals intent */
|
|
38
|
+
int active_user_count = get_active_users(db);
|
|
39
|
+
bool is_authenticated = token_validate(token);
|
|
40
|
+
|
|
41
|
+
#define MAX_RETRY_ATTEMPTS 3
|
|
42
|
+
|
|
43
|
+
typedef struct {
|
|
44
|
+
int id;
|
|
45
|
+
const char *name;
|
|
46
|
+
const char *email;
|
|
47
|
+
} user_t;
|
|
48
|
+
|
|
49
|
+
int user_find_by_email(const char *email, user_t *out_user);
|
|
50
|
+
|
|
51
|
+
/* BAD: Abbreviated, unclear, inconsistent */
|
|
52
|
+
int auc = getAU(db);
|
|
53
|
+
bool auth = tokVal(tok);
|
|
54
|
+
#define n 3
|
|
55
|
+
typedef struct { int Id; char *Name; } User;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Boolean Naming
|
|
59
|
+
|
|
60
|
+
Prefix with `is_`, `has_`, `can_`, `should_`:
|
|
61
|
+
|
|
62
|
+
```c
|
|
63
|
+
bool is_active = true;
|
|
64
|
+
bool has_permission = check_access(user, resource);
|
|
65
|
+
bool can_publish = (post->status == STATUS_DRAFT);
|
|
66
|
+
bool should_notify = user->preferences.notifications_enabled;
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Brace Style (K&R)
|
|
72
|
+
|
|
73
|
+
Opening brace on the same line as the statement. Functions may optionally place the brace on the next line (BSD/Allman variant), but K&R is preferred for consistency.
|
|
74
|
+
|
|
75
|
+
```c
|
|
76
|
+
/* GOOD: K&R brace style */
|
|
77
|
+
if (count > 0) {
|
|
78
|
+
process_items(items, count);
|
|
79
|
+
} else {
|
|
80
|
+
log_warn("no items to process");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for (size_t i = 0; i < len; i++) {
|
|
84
|
+
buffer[i] = 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
typedef struct {
|
|
88
|
+
int id;
|
|
89
|
+
char *name;
|
|
90
|
+
} user_t;
|
|
91
|
+
|
|
92
|
+
int parse_config(const char *path, config_t *out) {
|
|
93
|
+
FILE *fp = fopen(path, "r");
|
|
94
|
+
if (!fp) {
|
|
95
|
+
return -1;
|
|
96
|
+
}
|
|
97
|
+
/* ... */
|
|
98
|
+
fclose(fp);
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* BAD: Allman/GNU style (inconsistent with project) */
|
|
103
|
+
if (count > 0)
|
|
104
|
+
{
|
|
105
|
+
process_items(items, count);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Function Design
|
|
112
|
+
|
|
113
|
+
### Size and Parameter Limits
|
|
114
|
+
|
|
115
|
+
| Element | Guideline |
|
|
116
|
+
|---|---|
|
|
117
|
+
| Function body | Under 30 lines of logic, max 50 |
|
|
118
|
+
| Source file | Under 500 lines, max 800 |
|
|
119
|
+
| Header file | Under 200 lines, max 400 |
|
|
120
|
+
| Parameters | Max 5; use a struct/options for more |
|
|
121
|
+
| Nesting depth | Max 3 levels; extract helper functions |
|
|
122
|
+
|
|
123
|
+
### Early Returns with Guard Clauses
|
|
124
|
+
|
|
125
|
+
```c
|
|
126
|
+
/* GOOD: Guard clauses reduce nesting */
|
|
127
|
+
int user_create(const create_request_t *req, user_t *out) {
|
|
128
|
+
if (!req || !out) {
|
|
129
|
+
return ERR_NULL_PARAM;
|
|
130
|
+
}
|
|
131
|
+
if (strlen(req->email) == 0) {
|
|
132
|
+
return ERR_VALIDATION;
|
|
133
|
+
}
|
|
134
|
+
if (user_exists_by_email(req->email)) {
|
|
135
|
+
return ERR_ALREADY_EXISTS;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Main logic at base indentation */
|
|
139
|
+
out->id = next_id();
|
|
140
|
+
out->name = strdup(req->name);
|
|
141
|
+
out->email = strdup(req->email);
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* BAD: Deeply nested conditional logic */
|
|
146
|
+
int user_create(const create_request_t *req, user_t *out) {
|
|
147
|
+
if (req && out) {
|
|
148
|
+
if (strlen(req->email) > 0) {
|
|
149
|
+
if (!user_exists_by_email(req->email)) {
|
|
150
|
+
out->id = next_id();
|
|
151
|
+
out->name = strdup(req->name);
|
|
152
|
+
out->email = strdup(req->email);
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
return ERR_ALREADY_EXISTS;
|
|
156
|
+
}
|
|
157
|
+
return ERR_VALIDATION;
|
|
158
|
+
}
|
|
159
|
+
return ERR_NULL_PARAM;
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Header Guards
|
|
166
|
+
|
|
167
|
+
### Preferred: `#pragma once`
|
|
168
|
+
|
|
169
|
+
```c
|
|
170
|
+
/* GOOD: Simple, no name collisions */
|
|
171
|
+
#pragma once
|
|
172
|
+
|
|
173
|
+
#include <stddef.h>
|
|
174
|
+
#include <stdbool.h>
|
|
175
|
+
|
|
176
|
+
typedef struct {
|
|
177
|
+
int id;
|
|
178
|
+
char *name;
|
|
179
|
+
} user_t;
|
|
180
|
+
|
|
181
|
+
int user_create(const char *name, user_t *out);
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Alternative: Traditional Include Guards
|
|
185
|
+
|
|
186
|
+
```c
|
|
187
|
+
/* ACCEPTABLE: Required for some compilers or coding standards */
|
|
188
|
+
#ifndef MYPROJECT_USER_H
|
|
189
|
+
#define MYPROJECT_USER_H
|
|
190
|
+
|
|
191
|
+
#include <stddef.h>
|
|
192
|
+
|
|
193
|
+
/* ... */
|
|
194
|
+
|
|
195
|
+
#endif /* MYPROJECT_USER_H */
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Pattern**: `PROJECT_DIRECTORY_FILENAME_H` for traditional guards to avoid collisions.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Include Order
|
|
203
|
+
|
|
204
|
+
```c
|
|
205
|
+
/* 1. Corresponding header (for .c files) */
|
|
206
|
+
#include "myproject/user.h"
|
|
207
|
+
|
|
208
|
+
/* 2. C standard library */
|
|
209
|
+
#include <assert.h>
|
|
210
|
+
#include <stdbool.h>
|
|
211
|
+
#include <stddef.h>
|
|
212
|
+
#include <stdio.h>
|
|
213
|
+
#include <stdlib.h>
|
|
214
|
+
#include <string.h>
|
|
215
|
+
|
|
216
|
+
/* 3. POSIX / system headers */
|
|
217
|
+
#include <unistd.h>
|
|
218
|
+
#include <sys/types.h>
|
|
219
|
+
|
|
220
|
+
/* 4. Third-party libraries */
|
|
221
|
+
#include <cJSON.h>
|
|
222
|
+
#include <curl/curl.h>
|
|
223
|
+
|
|
224
|
+
/* 5. Project headers */
|
|
225
|
+
#include "myproject/config.h"
|
|
226
|
+
#include "myproject/error.h"
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Rule**: Alphabetical within each group. Blank line between groups. The corresponding header is always first to verify it is self-contained.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Const Correctness
|
|
234
|
+
|
|
235
|
+
```c
|
|
236
|
+
/* GOOD: Const on pointers that should not be modified */
|
|
237
|
+
void print_user(const user_t *user) {
|
|
238
|
+
printf("Name: %s\n", user->name);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* GOOD: Const on data that functions should not mutate */
|
|
242
|
+
int count_active(const user_t *users, size_t len) {
|
|
243
|
+
int count = 0;
|
|
244
|
+
for (size_t i = 0; i < len; i++) {
|
|
245
|
+
if (users[i].is_active) {
|
|
246
|
+
count++;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return count;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* GOOD: Const for string parameters */
|
|
253
|
+
int parse_config(const char *path, config_t *out);
|
|
254
|
+
|
|
255
|
+
/* BAD: Missing const -- caller cannot trust function will not modify data */
|
|
256
|
+
int count_active(user_t *users, size_t len);
|
|
257
|
+
void print_user(user_t *user);
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Static for Internal Linkage
|
|
263
|
+
|
|
264
|
+
```c
|
|
265
|
+
/* GOOD: Static functions are file-private (internal linkage) */
|
|
266
|
+
static int validate_email(const char *email) {
|
|
267
|
+
if (!email || strlen(email) == 0) {
|
|
268
|
+
return -1;
|
|
269
|
+
}
|
|
270
|
+
return strchr(email, '@') ? 0 : -1;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* GOOD: Static variables for file-scoped state */
|
|
274
|
+
static int s_initialized = 0;
|
|
275
|
+
static config_t s_config;
|
|
276
|
+
|
|
277
|
+
/* Public API function (declared in header) */
|
|
278
|
+
int config_init(const char *path) {
|
|
279
|
+
if (s_initialized) {
|
|
280
|
+
return ERR_ALREADY_INIT;
|
|
281
|
+
}
|
|
282
|
+
int rc = parse_config_file(path, &s_config);
|
|
283
|
+
if (rc == 0) {
|
|
284
|
+
s_initialized = 1;
|
|
285
|
+
}
|
|
286
|
+
return rc;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* BAD: Non-static helper visible to linker -- potential name collision */
|
|
290
|
+
int validate_email(const char *email) { /* ... */ }
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Typedef Conventions
|
|
296
|
+
|
|
297
|
+
```c
|
|
298
|
+
/* GOOD: Typedef structs with _t suffix */
|
|
299
|
+
typedef struct {
|
|
300
|
+
int id;
|
|
301
|
+
char *name;
|
|
302
|
+
char *email;
|
|
303
|
+
} user_t;
|
|
304
|
+
|
|
305
|
+
/* GOOD: Typedef enums */
|
|
306
|
+
typedef enum {
|
|
307
|
+
STATUS_OK = 0,
|
|
308
|
+
STATUS_ERROR = -1,
|
|
309
|
+
STATUS_TIMEOUT = -2,
|
|
310
|
+
} status_t;
|
|
311
|
+
|
|
312
|
+
/* GOOD: Opaque types for encapsulation */
|
|
313
|
+
/* In header: */
|
|
314
|
+
typedef struct database database_t;
|
|
315
|
+
|
|
316
|
+
/* In source: */
|
|
317
|
+
struct database {
|
|
318
|
+
void *handle;
|
|
319
|
+
char *connection_string;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
/* BAD: No typedef, verbose usage everywhere */
|
|
323
|
+
struct user {
|
|
324
|
+
int id;
|
|
325
|
+
char *name;
|
|
326
|
+
};
|
|
327
|
+
void print(struct user *u); /* Requires 'struct' keyword each time */
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Anti-Patterns
|
|
333
|
+
|
|
334
|
+
| Anti-Pattern | Problem | Correct Approach |
|
|
335
|
+
|---|---|---|
|
|
336
|
+
| camelCase or PascalCase for functions | Inconsistent with C ecosystem | `snake_case` for all functions and variables |
|
|
337
|
+
| Hungarian notation (`iCount`, `szName`) | Adds noise, types change | Descriptive `snake_case` names |
|
|
338
|
+
| Single-letter variable names | Unreadable outside tiny loops | Full descriptive names; `i`, `j`, `n` only for loop counters |
|
|
339
|
+
| Missing `const` on pointer parameters | Caller cannot trust immutability | Add `const` to all read-only pointer params |
|
|
340
|
+
| Non-static file-local functions | Pollutes global symbol table, name collisions | Mark all internal functions `static` |
|
|
341
|
+
| Macro constants for typed values | No type safety, no scope | Use `enum` or `static const` where possible |
|
|
342
|
+
| Functions over 50 lines | Hard to read, test, and maintain | Extract helper functions |
|
|
343
|
+
| Deep nesting (>3 levels) | Cognitive complexity | Guard clauses, early returns, extract functions |
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
_Consistency is the highest virtue in C style. Write code that reads like well-organized prose: clear names, flat structure, explicit intent._
|