printf: treat a -- past the format as an argument - #14394
Open
Socialpranker wants to merge 1 commit into
Open
Conversation
Only a `--` written before FORMAT ends the options; afterwards every operand is data, so `printf '%s\n' --` prints `--`. clap swallowed the first `--` wherever it appeared, dropping the operand. The same holds for `--help` and `--version`, which GNU honors only as the first operand.
|
GNU testsuite comparison: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
printflost a--operand that came after the format string:--helpspells out the two mutually exclusive forms:Options are an alternative to FORMAT, not something that can follow it. So
GNU looks for
--,--helpand--versiononly in the very firstoperand; from FORMAT onwards everything is data, including further
--.The fix
print_formattedhanded the arguments to clap unchanged, and clap ends theoptions at the first
--it sees anywhere, so a--in argument positionwas consumed. A new
mark_end_of_optionsinserts an explicit--in frontof the format operand when the caller did not already write one there,
which pins the terminator to the only place GNU accepts it. A leading
--help/--versionis stepped over so both still work as the soleoperand; past that point they reach the formatter as ordinary arguments.
The change is confined to argument marshalling — the formatter, the
diagnostics capture (which still sees the arguments as typed) and the
excess-argument warning are untouched.
How the GNU behavior was established
By running the installed GNU coreutils 9.11 binary (Homebrew,
gprintf) asa black box:
printf -- '%s\n' a,printf '%s\n' --,printf '%s %s\n' -- --,printf -- -- x,printf -- --help,printf '%s' --help,printf -- --version,printf '%s' -- --version,printf --help,printf --version,printf,printf -v, and diffingagainst uutils. I did not read GNU coreutils source.
Testing
tests/by-util/test_printf.rs:leading_double_dash_ends_the_options,double_dash_after_the_format_is_an_argument,double_dash_as_the_format_is_printed_literally,help_and_version_past_the_format_are_arguments. Mutation-checked:reverting
printf.rsalone makes two of them fail.cargo test --features printf --test tests test_printf: 145 passed, 0failed (141 before, plus the four new ones).
cargo clippy -p uu_printf --all-targets -- -D warnings: clean.cargo fmt --check: clean.printfinvocations: mismatches 4 -> 3, no case regressed. (The two remaining
real mismatches are unrelated:
%aformatting, and a harness quotingartifact.)
Disclosure
Prepared with AI assistance (Claude Opus 5, via Claude Code), per the AI
policy in CONTRIBUTING.md. Every GNU behavior quoted above came from
running the installed binary, not from reading GPL source. All testing was
run locally.