On Sat, Feb 22, 2025 at 9:49 AM Andreas Schwab <sch...@linux-m68k.org>
wrote:

> On Feb 22 2025, Phi Debian wrote:
>
> > I forgot to mention your trick to nuke the fmt reuse still works
> >
> > $ printf '%s %s %s %999$s' A B C D E F G
> > A B C
>
> As long as NL_ARGMAX >= 999.
>

Sounds like I was over optimistic

$ echo $KSH_VERSION
Version AJM 93u+m/1.1.0-alpha+b5087279 2025-01-15
$ printf '%s %s %999$s\n' 1 2 3 4 5 6 7 8
1 2
$ unset A B C D E F G H
$ printf '%s %s %999$s\n'  A B C D E F G H
./ksh: printf: C: parameter not set
./ksh: printf: D: parameter not set
./ksh: printf: E: parameter not set
./ksh: printf: F: parameter not set
./ksh: printf: G: parameter not set
./ksh: printf: H: parameter not set
A B
$

I admit I didn't entered a way big arg index (exceeding the actual number
of args) in the QA suite for ksh93, will do soon, along with a fix to avoid
such wrong error output.

$ getconf NL_ARGMAX
4096

The idea to nuke fmt re-use is to use a index arg number bigger then the
expected number of args, and if unknown got for the max :-)

Thanx for raising this...

But here we are talking bash 'possible' implementation of printf fmt
indexed args access, and I wanted to share what I did for ksh93, kind of
heads up of pitfall to watch out.

So the implementation make '%s %s %s' as '%(seq++)s %(seq++)s %(seq++)'
with (seq) a theorical syntax don't exist in reality.

The problem that led me to go with seq++ access of unumbered args, i.e
internally treat them as numbered in seq++ is that mix'n'match of
numbered/unumbered not only occurs for each % but inside them i.e

'%s %2% %s' is mix'n'match for %

but indexed access also occurs in width.prec as

Unnumbered
$ printf '%*s\n'   2 4
 4

numbered (works as documented in sprintf(3) )
$ printf '%2$*1$s\n'   2 4
 4

Mix'n'match UGLY, don't use, but if you insist
printf '%2$*s\n'   2 4 6 8
 4
     8
Here the arg value is indexed at 2$ but the width is not (unumbered), so
here with 'my' implementation treat this like '%2$*(seq++)$s\n' really
fetching the correct width, yet an explicit *1$ is much preferable.

With an implementation (as was ksh93 when it was plain bugged) the
unumbered would be next to last index and would be similar to %2$*3$s and
would not work.

By applying the rule (seq++) for any unumbered  not only it works (in the
sense produce something predictable), and it goes along with ftm reuse
nicely.

So this was my best guess for something that was ugly from the start, i.e
mixin numbered/unumbered.

The other approach consisting of refusing mix'n'match is more complicated
internally, because it force a double pass on fmt string, while the seq++
just walk produce thing (not necessarilly to yourt liking) and is
predictable.

This this the reflexion that led me to this implementation...

Reply via email to