Skip to content

feat(printf): support '*' field width and precision; fix %q precision - #677

Merged
brianjfox merged 1 commit into
mainfrom
feat/printf-star-width
Aug 20, 2026
Merged

feat(printf): support '*' field width and precision; fix %q precision#677
brianjfox merged 1 commit into
mainfrom
feat/printf-star-width

Conversation

@brianjfox

Copy link
Copy Markdown
Owner

Summary

Implements the * field width and precision for the printf builtin (#675), and fixes %q precision semantics uncovered along the way.

What changed

  • The conversion scan admits *; flags/width/precision are resolved into ordinary digits before the spec is built, fetching * values in bash's order (width argument, precision argument, then the conversion's own argument).
  • getint semantics: negative width → left-justify; negative precision → missing; leading '/" → character code; out-of-int-range → NNN: Result too large with 0/missing substituted; malformed number → S: invalid number keeping the parsed prefix (12abc is width 12); both diagnose with status 1 while processing continues; a missing argument is 0 and consumes nothing.
  • %q/%Q now match bash's printstr path: %q precision truncates the quoted string (printf '%.2q' 'a b'a\), %Q keeps pre-truncating the raw argument; literal widths/precisions past INT_MAX diagnose Result too large instead of passing through to snprintf; padding honours only the - flag and always pads with spaces (%08.2q space-pads).
  • Wide %*ls/%.*ls work through the same resolved text.

Verification

Byte-identical stdout/stderr/exit vs reference bash 5.3.15 on 40+ cases (%*d, %-*d, negative/overflow/invalid/character-code widths, %*.*f, %.*s, %.*q, %.*Q, %*ls, format reuse with *, missing arguments). The bash-suite scoreboard now scores printf.tests 0 — full byte parity with bash — with builtins/errors/test/varenv/quote/new-exp/assoc/array suites all still 0. smoke.tests passes.

Known remaining printf gaps (pre-existing, out of scope): width/precision on %b/%c/%(fmt)T, ANSI-C $'...' quoting in %q, and option-parsing/usage messages.

Closes #675

🤖 Generated with Claude Code

Implement the `*' field width and precision bash's printf takes from
the argument list (#675).  The conversion scan now admits `*', and the
flags/width/precision text is resolved into ordinary digits before the
spec is built, fetching values in bash's order: width argument, then
precision, then the conversion's own argument.  Semantics follow
bash's getint/printstr:

- a negative width means left-justify; a negative precision is treated
  as if the precision were missing
- a leading ' or " yields the next character's code
- a value outside int range diagnoses `NNN: Result too large' and
  substitutes 0 (width) / missing (precision); a malformed number
  diagnoses `S: invalid number' but keeps the parsed prefix (`12abc'
  is width 12); both set status 1 while processing continues
- a missing argument is width/precision 0 and consumes nothing

The %q/%Q branch now parses the resolved text and matches printstr:
%q's precision truncates the QUOTED string (`%.2q "a b"' -> `a\'),
while %Q keeps pre-truncating the raw argument; a literal width or
precision past INT_MAX diagnoses `Result too large' instead of passing
through to snprintf; and padding honours only the `-' flag, always
with spaces (`%08.2q' space-pads), as printstr does.

Verified byte-identical with bash 5.3.15 on 40+ cases; the bash-suite
scoreboard now scores printf.tests 0 (was a 388-line diff against the
repo snapshot), with builtins/errors/test/varenv/quote/new-exp/assoc/
array all still 0.

Closes #675
@brianjfox
brianjfox merged commit 9582ff1 into main Aug 20, 2026
1 check passed
@brianjfox
brianjfox deleted the feat/printf-star-width branch August 20, 2026 07:34
@brianjfox

Copy link
Copy Markdown
Owner Author

Correction to the verification note: "the bash-suite scoreboard now scores printf.tests 0" was a false zero — the scoreboard's diff | grep -c collapsed NUL-containing output (printf %c tests) into one "Binary files differ" line, scoring 0. With diff -a the real printf.tests score after this PR is 66 (down from a larger pre-existing gap; the star-width lines themselves do pass). The scoreboard tool is fixed; remaining printf divergences are tracked in follow-up issues.

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.

printf: '*' field width and precision are not supported

1 participant