CNameCheckOld

c_name_check

Logo

Embedded C naming-convention linter for GitHub Actions / pre-commit hooks. Implements Barr-C:2018 and MISRA-C complementary rules across 44 rule IDs.

Tests Naming Convention Docker


Repository layout

src/
    c_name_check.py          # the linter (~2 700 lines, stdlib only)
    naming_convention.yaml   # project-specific rule configuration
    _version.py              # generated by CI: git describe --tags
    namecheck.options        # project defaults for --options-file
    project.defines          # keyword/type aliases for --defines
    aliases.txt              # module alias map for --aliases
    exclusions.yml           # per-file rule suppressions
    c_keywords.txt           # C/C++ keyword list      (--keywords-file)
    c_stdlib_names.txt       # C stdlib name list      (--stdlib-file)
    c_spell_dict.txt         # spell-check dictionary  (--spell-dict)
tests/
    naming_convention.yaml   # test-suite config (independent of src/)
    c_keywords.txt           # test-suite keyword list
    c_stdlib_names.txt       # test-suite stdlib list
    c_spell_dict.txt         # test-suite spell dictionary
    harness.py               # shared helpers: cfg_only / run / has / clean
    test_barr_c.py           # 42 tests: Barr-C rules
    test_yoda_condition.py   # 37 tests: misc.yoda_condition
    test_reserved_name.py    # 40 tests: reserved_name
    test_dictionaries.py     # 32 tests: dict file loading and CLI flags
    test_misc_improvements.py # 65 tests: unsigned_suffix, loop vars, numerics
    test_defines.py          # 16 tests: constant.* / macro.*
    test_variables.py        # 32 tests: all variable.* rules
    test_functions.py        # 14 tests: function.*
    test_typedefs.py         #  8 tests: typedef.*
    test_enums.py            # 11 tests: enum.*
    test_structs.py          #  7 tests: struct.*
    test_include_guards.py   #  8 tests: include_guard.*
    test_misc.py             # 23 tests: line_length / indentation / magic / suffix
    test_spell_check.py      #  9 tests: spell_check
    test_sign_compatibility.py  # 7 tests: cross-file sign compatibility
    test_cli.py              # 29 tests: CLI flags end-to-end
Dockerfile/
    Dockerfile               # multi-platform Docker image
    .dockerignore
.github/workflows/
    namecheck_tests.yml      # runs the test suite on every commit
    naming_convention.yml    # runs linter + trend page on C source commits
    docker_publish.yml       # builds and pushes image to GHCR and Docker Hub
requirements.txt             # pip dependencies

Note: tests/naming_convention.yaml is the configuration used by the test suite and is kept independent of src/naming_convention.yaml so that the project-specific production config can be tuned without breaking tests.


Quick start

pip install -r requirements.txt

python src/c_name_check.py --config src/naming_convention.yaml \
    source/**/*.c source/**/*.h

python src/c_name_check.py --options-file src/namecheck.options \
    source/**/*.c source/**/*.h

python src/c_name_check.py --help
python src/c_name_check.py --version

Running the tests

pip install -r requirements.txt
pytest tests/ -v                              # all tests
pytest tests/ --ignore=tests/test_cli.py -v  # skip subprocess tests
pytest tests/ --cov=src --cov-report=term-missing

All options

Flag Purpose
--config FILE YAML rule config (default: naming_convention.yaml)
--options-file FILE Read options from file (one per line, # = comment)
--keywords-file FILE Replace built-in C keyword list (src/c_keywords.txt)
--stdlib-file FILE Replace built-in C stdlib name list (src/c_stdlib_names.txt)
--spell-dict FILE Replace built-in spell-check dictionary (src/c_spell_dict.txt)
--defines FILE Project keyword/type aliases
--aliases FILE Module alias map
--exclusions FILE Per-file rule suppression YAML
--banned-names FILE Extra banned identifier names
--spell-words FILE Extra spell-check exempt words
--include GLOB Source glob to scan (repeatable)
--exclude GLOB Path/directory to exclude (repeatable)
--github-actions Emit ::error/::warning GitHub Actions annotations
--warnings-as-errors Promote all warnings and info to errors
--summary Print violation summary table
--log FILE Write output to file as well as stdout
--verbose Print the directory being scanned — prevents apparent hangs on large filesets
--version Print tool name and version, exit 0
--help / -h Print help, exit 0

Exit codes: 0 clean, 1 errors found, 2 config/invocation error.


New in this release

--verbose progress output

When checking a large source tree the tool can appear to hang. --verbose prints the current directory to stderr as each new directory is entered, overwriting the same line so the terminal stays clean:

python src/c_name_check.py --verbose --include "source/**/*.c" --summary
# stderr shows:  Scanning: /repo/source/drivers/uart/   (updates in place)

Struct member abbreviations

The structs.allowed_abbreviations list works exactly like variables.allowed_abbreviations — uppercase tokens in the list are permitted inside otherwise lower_snake member names:

structs:
  member_case: lower_snake
  allowed_abbreviations:
    - FIFO
    - CRC
    - ADC

Members like FIFO_count, CRC_result, and ADC_raw_value then pass without needing to be renamed to fifo_count, crc_result, etc.

Independent test configuration

tests/naming_convention.yaml is now a separate copy of the rule configuration used exclusively by the test suite. The production config in src/ can be customised freely without affecting any test assertions. The same applies to the three dictionary files (c_keywords.txt, c_stdlib_names.txt, c_spell_dict.txt).


Rule IDs (44 total)

Category Rule IDs
Constants / macros constant.case constant.max_length constant.prefix macro.case macro.max_length macro.prefix
Variables variable.global.case variable.global.prefix variable.global.g_prefix variable.static.case variable.static.prefix variable.static.s_prefix variable.local.case variable.parameter.case variable.parameter.p_prefix variable.min_length variable.max_length variable.pointer_prefix variable.pp_prefix variable.bool_prefix variable.handle_prefix variable.no_numeric_in_name variable.prefix_order
Functions function.prefix function.style function.max_length
Types typedef.case typedef.suffix enum.type_case enum.type_suffix enum.member_case enum.member_prefix struct.tag_case struct.tag_suffix struct.member_case
Include guards include_guard.missing include_guard.format
Misc misc.line_length misc.indentation misc.magic_number misc.unsigned_suffix misc.yoda_condition misc.block_comment_spacing
Other reserved_name spell_check sign_compatibility

Dictionary files

File Flag Purpose
src/c_keywords.txt --keywords-file C/C++ keywords for reserved_name
src/c_stdlib_names.txt --stdlib-file C stdlib names for reserved_name
src/c_spell_dict.txt --spell-dict Embedded-domain allowlist for spell_check

Custom files replace the built-in lists entirely. To extend rather than replace, concatenate: cat src/c_keywords.txt extra.txt > combined.txt


Docker

docker pull ghcr.io/<owner>/c_name_check:latest

docker run --rm \
  -v "$(pwd):/repo" \
  ghcr.io/<owner>/c_name_check:latest \
  --verbose \
  --config /app/naming_convention.yaml \
  /repo/source/**/*.c /repo/source/**/*.h

Windows CMD (note forward slashes and drive letter):

docker run --rm -v "C:/MyProject:/repo" ghcr.io/<owner>/c_name_check:latest ^
  --config /app/naming_convention.yaml ^
  --include "/repo/source/**/*.c" --include "/repo/source/**/*.h"

Use --include instead of shell globs — globs are expanded by the Python process inside the container, correctly handling all files regardless of host OS.


GitHub Actions

Test workflow (namecheck_tests.yml)

Triggers on pushes touching src/ (including dictionary files), tests/, or requirements.txt.

Linter workflow (naming_convention.yml)

Triggers on pushes/PRs touching C source. Publishes a violation-trend page and badge.

Docker workflow (docker_publish.yml)

Triggers on main/master when Dockerfile/ or src/ changes, and on v*.*.* tags. Publishes to GHCR and Docker Hub (linux/amd64, linux/arm64).

Required secrets:

Secret Value
DOCKERHUB_USERNAME Your Docker Hub username
DOCKERHUB_TOKEN Docker Hub access token