Skip to content

Commit

Permalink
printf: ignore args case (#532)
Browse files Browse the repository at this point in the history
* I discovered incorrect looping behaviour for: perl printf a b c
* In the loop, b and c are never shifted off ARGV list, so it never terminates
* The 1st argument is interpreted as the format string, but it contains no format specifiers
* bash-builtin printf, as well as GNU and OpenBSD versions agree that arguments b and c should not be used
* On OpenBSD there is no pdksh builtin printf to test against
* Text in the standards document is not very helpful: "If the format operand contains no conversion specifications and argument operands are present, the results are unspecified." [1]

1. https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
  • Loading branch information
mknos committed Apr 4, 2024
1 parent 964afac commit a3165e7
Showing 1 changed file with 5 additions and 1 deletion.
6 changes: 5 additions & 1 deletion bin/printf
Expand Up @@ -31,7 +31,7 @@ unless (@ARGV) {
my @fmt;
my $format = shift;
exit EX_SUCCESS unless (length $format);
parse_fmt();
@ARGV = () if (parse_fmt() == 0);
do {
foreach my $part (@fmt) {
if ($part->[0] eq 'str') {
Expand Down Expand Up @@ -60,21 +60,25 @@ sub parse_fmt {
my $f = $format;
$f =~ s/\%c/\%\.1s/g; # standard printf: %c == 1st char

my $i = 0;
while (length $f) {
if ($f =~ s/\A([^%]+)//) {
push @fmt, [ 'str', $1 ];
} elsif ($f =~ s/\A\%\%//) {
push @fmt, [ 'str', '%%' ];
} elsif ($f =~ s/\A(\%[0-9\.\-]*s)//) {
push @fmt, [ 'sfmt', $1 ];
$i++;
} elsif ($f =~ s/\A(\%[0-9\.\-]*[diouXx])//) {
push @fmt, [ 'ifmt', $1 ];
$i++;
} elsif ($f =~ s/\A(\%[0-9\.\-]*[a-zA-Z])//) {
push @fmt, [ 'str', $1 ]; # unsupported
} else {
die "internal error";
}
}
return $i;
}

sub oct2char {
Expand Down

0 comments on commit a3165e7

Please sign in to comment.