NetBSD Problem Report #60499
From www@netbsd.org Fri Jul 24 21:25:19 2026
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits)
client-signature RSA-PSS (2048 bits))
(Client CN "mail.netbsd.org", Issuer "YR2" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id AAD8B1A923B
for <gnats-bugs@gnats.NetBSD.org>; Fri, 24 Jul 2026 21:25:19 +0000 (UTC)
Message-Id: <20260724212518.AE22A1A923C@mollari.NetBSD.org>
Date: Fri, 24 Jul 2026 21:25:18 +0000 (UTC)
From: uwe@stderr.spb.ru
Reply-To: uwe@stderr.spb.ru
To: gnats-bugs@NetBSD.org
Subject: printf(1) doesn't support positional arguments (%n$...)
X-Send-Pr-Version: www-1.0
X-From4GNATS: "uwe@stderr.spb.ru via gnats" <gnats-admin@NetBSD.org>
>Number: 60499
>Category: bin
>Synopsis: printf(1) doesn't support positional arguments (%n$...)
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kre
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jul 24 21:30:01 +0000 2026
>Last-Modified: Sat Jul 25 13:30:02 +0000 2026
>Originator: Valery Ushakov
>Release: NetBSD 11.99
>Organization:
>Environment:
NetBSD aurinko 11.99.7 NetBSD 11.99.7 (ULTRA1) #0: Thu Jul 23 00:59:41 MSK 2026 uwe@supi:/home/uwe/work/netbsd/cvs/src/sys/arch/sparc64/compile/ULTRA1 sparc64
>Description:
printf(1) doesn't seem to support positional parameters "%n$..."
Issue 8 seems to prescribe it:
https://pubs.opengroup.org/onlinepubs/9799919799/utilities/printf.html
though bash doesn't seem to do it either.
>How-To-Repeat:
I wrote
printf '\tR%1$d, G%1$d = R%1$d,\n' $(seq 0 7)
expecting it to generate me a bit of code (shell-command-on-region)
but
$ printf: %1$: invalid directive
R$
PS: note also, how the format is not checked in advance and the initial
prefix is printed.
Shameless plug:
https://hg.sr.ht/~nbuwe/printf_checkformat
is like our fmtcheck(3) but does positional parameters.
>Fix:
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: bin-bug-people->kre
Responsible-Changed-By: kre@NetBSD.org
Responsible-Changed-When: Sat, 25 Jul 2026 01:53:41 +0000
Responsible-Changed-Why:
I will look into this one too, I already have (or had once) code which "worked".
From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60499: printf(1) doesn't support positional arguments (%n$...)
Date: Sat, 25 Jul 2026 09:23:12 +0700
Date: Fri, 24 Jul 2026 21:30:01 +0000 (UTC)
From: "uwe@stderr.spb.ru via gnats" <gnats-admin@NetBSD.org>
Message-ID: <20260724213001.C55141A923D@mollari.NetBSD.org>
| printf(1) doesn't seem to support positional parameters "%n$..."
| Issue 8 seems to prescribe it:
It does. If it didn't, we would most likely have support!
The problem is that I simply find the spec in POSIX absurd, so rather
that implement that, I implemented (committed really) nothing.
Note that the issue doesn't affect any normal use of the things,
but would have affected your test case (potentially):
| printf '\tR%1$d, G%1$d = R%1$d,\n' $(seq 0 7)
That is, when there are more args (8 in that case) than are used
by the format string (just 1 here).
printf(3) is not affected at all by these issues, it never attempts
to repeat the format string, to use up all the args (it has no way to
determine how many of them there were) - one potential solution for
printf(1) would be to make it the same, so if there are any positional
args, the format string would only be used once.
The would easily deal with all the issues when the positional args are
being used for their original purpose - supporting output of i18n strings,
where different cultures output messages with the parameters in different
orders, and not necessarily using all of the args (any of them might be
omitted).
It wouldn't however handle people who have decided that printf(1)'s
positional params can be (ab)used to do all kinds of other tricks, like
the one you are attempting above, which could just as easily be
written
for A in $(seq 0 7)
do
printf '\tR%d, G%d = R%d,\n' "$A" "$A" "$A"
done
If you do it that way (and something like this is *always* possible
in these kinds of cases) there is never any ambiguity about what is
intended - there's just a little less opportunity to show off just
how clever you are.
There are other (not as simple as that one, but still relatively sane)
potential solutions, which are not as broken as what POSIX prescribes
however -- personally though I kind of like the simple elegance of
simply ignoring stray extra args when there are positional params, but
none happens to select the final args -- which can easily happen when
an internationised printf usage (where the format string comes from a
message catalog) and the language in question happens not to need the
final arg. printf(3) wouldn't care, printf(1) probably shouldn't either.
| $ printf: %1$: invalid directive
| R$
| PS: note also, how the format is not checked in advance and the initial
| prefix is printed.
That is actually a requirement. I agree in most cases a fairly silly one,
but in general printf(1) is always required to print everything it has
accumulated up to the time an error is detected (including bogus results
of conversions in many cases).
kre
From: Valery Ushakov <uwe@stderr.spb.ru>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60499: printf(1) doesn't support positional arguments
(%n$...)
Date: Sat, 25 Jul 2026 11:47:09 +0300
On Sat, Jul 25, 2026 at 02:25:01 +0000, Robert Elz via gnats wrote:
> | printf(1) doesn't seem to support positional parameters "%n$..."
> | Issue 8 seems to prescribe it:
>
> It does. If it didn't, we would most likely have support!
>
> The problem is that I simply find the spec in POSIX absurd, so rather
> that implement that, I implemented (committed really) nothing.
I'm confused... "It does" and "implemented nothing" is kinda
contradictory.
$ /usr/bin/printf '%s %s\n' a b
a b
$ /usr/bin/printf '%2$s %1$s\n' a b
printf: %2$: invalid directive
> It wouldn't however handle people who have decided that printf(1)'s
> positional params can be (ab)used to do all kinds of other tricks, like
> the one you are attempting above,
Guilty as charched. But I often find implicit loop in printf
massively convenient :)
> there's just a little less opportunity to show off just
> how clever you are.
I don't think our shell is easily impressed, it's seen worse, and
no-one else sees those snippets of shell code that I type into my
emacs buffer only to immediately C-u M-| sh <RET> it.
-uwe
From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60499: printf(1) doesn't support positional arguments (%n$...)
Date: Sat, 25 Jul 2026 20:27:50 +0700
Date: Sat, 25 Jul 2026 08:50:02 +0000 (UTC)
From: "Valery Ushakov via gnats" <gnats-admin@NetBSD.org>
Message-ID: <20260725085002.ECDF71A923D@mollari.NetBSD.org>
| I'm confused... "It does" and "implemented nothing" is kinda
| contradictory.
"It does" was agreeing with you about what POSIX requires.
"implemented nothing" was my reaction to what POSIX requires.
| But I often find implicit loop in printf massively convenient :)
It is when not using positional args, and nothing is going to remove
that (I have even considered making it more flexible). But with
positional args the possibilities just get to be too mind boggling,
in the general case (the one you showed was trivial, easy to know
what was expected, but that's not always true, esp when they are
being used for the purpose for which they were designed.)
| I don't think our shell is easily impressed, it's seen worse, and
| no-one else sees those snippets of shell code that I type into my
| emacs buffer only to immediately C-u M-| sh <RET> it.
You mean you weren't aware of sh's phone home policy, where sh looks
at all the code it sees, and if it sees anything particularly sexy,
sends me a copy ???
kre
ps: just for the humour challenged, that last para wasn't serious, of course.
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.