Skip to content

feat: preprocessor for text configs - #50

Merged
TheWillard merged 3 commits into
mainfrom
feat/cfg-preprocessor
Nov 11, 2026
Merged

TheWillard merged 3 commits into
mainfrom
feat/cfg-preprocessor

Conversation

@TheWillard

Copy link
Copy Markdown
Contributor

Text configs treated every line starting with # as a comment: macros were left unexpanded (and failed to parse), #include was silently dropped. This adds the preprocessor, following PreProcessor Commands:

  • #define with arguments, variadic macros (__VA_ARGS__, __VA_OPT__, __VA_OPT_INV__, __VA_APPLY__, __VA_SELECT__), # and ##, multi-line bodies. #undef.
  • #if (comparisons, plus &&, ||, !, defined()), #ifdef, #ifndef, #else, #endif, also #elif. Nesting works.
  • #include "..." / <...>, relative and \ absolute paths, ... Nesting is limited to 32 levels, which also stops include cycles.
  • __has_include, __LINE__, __FILE__, __FILE_NAME__, __FILE_SHORT__, __COUNTER__, __COUNTER_RESET__, the date/time macros (UTC), __RAND_*. __ARMA__ and __ARMA3__ are predefined; game-dependent ones (__GAME_VER_MAJ__, __A3_DEBUG__, ...) can be set with Preprocessor::define.

Where the game differs from C, it follows the game:

  • Arguments are expanded before they're substituted, also for # and ##: QUOTE(GVAR(x)) gives "cba_main_x".
  • Arguments aren't trimmed (matches the wiki's FORMAT example output).
  • ## only removes itself, the whitespace around it stays: ACE's class ##weapon gives class weapon.
  • Single-quoted strings are expanded, double-quoted ones aren't. A # in a body that isn't followed by an argument is dropped.

Not copied: the game drops commas inside quoted macro arguments (MACRO("a, b") → "a b"), this keeps them.

API:

  • Preprocessor::new().with_resolver(...), define, undefine, preprocess(src, path), preprocess_path(path).
  • IncludeResolver: FsIncludeResolver for files on disk (include dirs like a P drive), or any closure Fn(&str, Option<&str>) -> io::Result<Option<IncludeFile>>; join_include_path resolves virtual paths for closures serving PBO contents.
  • Cfg::parse_config_with(src, path, &mut pp) and Cfg::parse_path(path, &mut pp).
  • Behavior change: Cfg::parse_config and Cfg::read now preprocess first. #include without a resolver is a PreprocessError instead of being skipped.

Checked against all 220 config.cpp of CBA_A3 and ACE3 (with \a3\ui_f includes stubbed as empty): all preprocess, in 1.8 s total, with no unexpanded macros left. 121 parse; the other 99 fail in the config parser on +=, arithmetic, numbers with leading zeros, hex numbers and class names starting with a digit, which comes next.

Text configs ignored every line starting with #, so macros were left
unexpanded and #include was dropped.

- rap::Preprocessor: #define (arguments, variadic __VA_* macros, # and
  ##, multi-line), #undef, #if/#ifdef/#ifndef/#else/#endif, #include,
  __has_include and the __XXX__ built-ins.
- Follows the game where it differs from C: arguments are expanded
  before # and ##, arguments are not trimmed, ## keeps the whitespace
  around it, single-quoted strings are expanded, double-quoted not.
- Includes go through IncludeResolver: FsIncludeResolver for files on
  disk, or any closure, with join_include_path for virtual paths.
- Cfg::parse_config and Cfg::read preprocess first, #include without a
  resolver is an error. Cfg::parse_config_with and Cfg::parse_path take
  a preprocessor.
/tmp/x/config.cpp on Linux was taken for a path of the game (\a3\...)
and only looked up in the include directories.
@codecov

codecov Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.16981% with 11 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...le-formats/src/real_virtuality/rap/preprocessor.rs 99.15% 11 Missing ⚠️
Files with missing lines Coverage Δ
...rma-file-formats/src/real_virtuality/rap/config.rs 85.41% <100.00%> (+1.88%) ⬆️
arma-file-formats/src/real_virtuality/rap/mod.rs 60.00% <ø> (+14.00%) ⬆️
...le-formats/src/real_virtuality/rap/preprocessor.rs 99.15% <99.15%> (ø)

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@TheWillard
TheWillard merged commit ec594dd into main Nov 11, 2026
2 checks passed
@TheWillard
TheWillard deleted the feat/cfg-preprocessor branch November 11, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant