POSIX Issue 8 will be obsoleting %b (escape sequence interpolation) so that future Issue 9 can change to having %b (binary literal output) that aligns with C2x. But since escape interpolation may still remain useful, POSIX suggested %#s (which is undefined in all versions of C) as a possible alias for the older %b behavior.
* src/printf.c (print_formatted, usage): Support %#s as an alias for %b, in order to open doors to future repurposing of %b to binary output while still allowing access to its old behavior. * doc/coreutils.texi (printf invocation): Document it. * NEWS: Likewise. * tests/printf/printf-quote.sh: Add unit test coverage. Fixes: https://bugs.gnu.org/65659 --- NEWS | 9 +++++++++ doc/coreutils.texi | 3 ++- src/printf.c | 9 ++++++--- tests/printf/printf-quote.sh | 4 +++- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index c00ff0cf2..2e2acc7cd 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,15 @@ GNU coreutils NEWS -*- outline -*- numfmt options like --suffix no longer have an arbitrary 127-byte limit. [bug introduced with numfmt in coreutils-8.21] +** Changes in behavior + + 'printf' now treats the format sequence '%#s' as an alias for the + older '%b' meaning escape sequence interpolation. It is anticipated + that a future version of coreutils will change the meaning of '%b' + to output binary literals, comparable to the meaning being added to + printf(3) by C23, which will leave '%#s' (which C does not specify) + as the only way to access the older behavior of escape + interpolation. * Noteworthy changes in release 9.4 (2023-08-29) [stable] diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 373a407ed..81a8ca4ff 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -13331,7 +13331,8 @@ printf invocation @item @kindex %b -An additional directive @samp{%b}, prints its +@kindex %#s +An additional directive @samp{%#s}, or its older alias @samp{%b}, prints its argument string with @samp{\} escapes interpreted in the same way as in the @var{format} string, except that octal escapes are of the form @samp{\0@var{ooo}} where @var{ooo} is 0 to 3 octal digits. If diff --git a/src/printf.c b/src/printf.c index 9670d8043..e8866d50e 100644 --- a/src/printf.c +++ b/src/printf.c @@ -38,7 +38,7 @@ Additional directive: - %b = print an argument string, interpreting backslash escapes, + %b, %#s = print an argument string, interpreting backslash escapes, except that octal escapes are of the form \0 or \0ooo. %q = print an argument string in a format that can be @@ -126,8 +126,9 @@ FORMAT controls the output as in C printf. Interpreted sequences are:\n\ "), stdout); fputs (_("\ %% a single %\n\ - %b ARGUMENT as a string with '\\' escapes interpreted,\n\ + %#s ARGUMENT as a string with '\\' escapes interpreted,\n\ except that octal escapes are of the form \\0 or \\0NNN\n\ + %b obsolescent alias for %#s\n\ %q ARGUMENT is printed in a format that can be reused as shell input,\n\ escaping non-printable characters with the proposed POSIX $'' syntax.\ \n\n\ @@ -509,7 +510,7 @@ print_formatted (char const *format, int argc, char **argv) putchar ('%'); break; } - if (*f == 'b') + if (*f == 'b' || (*f == '#' && f[1] == 's')) { /* FIXME: Field width and precision are not supported for %b, even though POSIX requires it. */ @@ -519,6 +520,8 @@ print_formatted (char const *format, int argc, char **argv) ++argv; --argc; } + if (*f == '#') + f++; break; } diff --git a/tests/printf/printf-quote.sh b/tests/printf/printf-quote.sh index d1671bd9d..33ce3018e 100755 --- a/tests/printf/printf-quote.sh +++ b/tests/printf/printf-quote.sh @@ -22,7 +22,8 @@ print_ver_ printf prog='env printf' # Equivalent output to ls --quoting=shell-escape -$prog '%q\n' '' "'" a 'a b' '~a' 'a~' "$($prog %b 'a\r')" > out +$prog '%q\n' '' "'" a 'a b' '~a' 'a~' "$($prog %b 'a\r')" \ + "$($prog %#s 'a\r')" > out cat <<\EOF > exp || framework_failure_ '' "'" @@ -31,6 +32,7 @@ a '~a' a~ 'a'$'\r' +'a'$'\r' EOF compare exp out || fail=1 -- 2.41.0