That's not a typo, just bad memory. I never used the feature, and it
seemed "obvious" to me that the right way to do this would be to have
it be a modifier, like ".". (Because "%12..." would, in every other
circumstance, be specifying a width of 12, and precision is indicated
by a *leading* punctuation mark. I just assumed that other extensions
would also use a leading punctuation mark.)
FWIW, from SUSv2/fprintf():
----v----
In format strings containing the %n$ form of a conversion specification,
a field width or precision may be indicated by the sequence *m$, where m
is a decimal integer in the range [1, {NL_ARGMAX}] giving the position
in the argument list (after the format argument) of an integer argument
containing the field width or precision, for example:
printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec);
The format can contain either numbered argument specifications (that is,
%n$ and *m$), or unnumbered argument specifications (that is, % and *),
but normally not both. The only exception to this is that %% can be
mixed with the %n$ form. The results of mixing numbered and unnumbered
argument specifications in a format string are undefined. When numbered
argument specifications are used, specifying the Nth argument requires
that all the leading arguments, from the first to the (N-1)th, are
specified in the format string.
----^----
I don't know if I've seen this yet on any BSD systems, but it appears
to be available in Linux these days.
Anecdote time! From lbzip2-0.17 (obsolete -- current version is 0.23),
----v----
/*
I have to replace this elegant construct with the lame one below, because
the Tru64 system I tested on chokes on the %N$*M$lu conversion
specification, even though it is certified UNIX 98 (I believe):
$ uname -s -r -v -m
OSF1 V5.1 2650 alpha
$ c89 -V
Compaq C V6.5-011 on Compaq Tru64 UNIX V5.1B (Rev. 2650)
Compiler Driver V6.5-003 (sys) cc Driver
http://www.opengroup.org/openbrand/register/brand2700.htm
And no, I won't factor this out.
28-JAN-2009 lacos
*/
#if 0
"%1$s: any worker tried to consume from splitter: %3$*2$lu\n"
"%1$s: any worker stalled : %4$*2$lu\n"
"%1$s: muxer tried to consume from workers : %5$*2$lu\n"
"%1$s: muxer stalled : %6$*2$lu\n"
"%1$s: splitter tried to consume from muxer : %7$*2$lu\n"
"%1$s: splitter stalled : %8$*2$lu\n",
pname, (int)sizeof(long unsigned) * (int)CHAR_BIT / 3 + 1,
s2w_q.av_or_eof.ccount, s2w_q.av_or_eof.wcount,
w2m_q.av_or_exit.ccount, w2m_q.av_or_exit.wcount,
m2s_q.av.ccount, m2s_q.av.wcount)
#else
# define FW ((int)sizeof(long unsigned) * (int)CHAR_BIT / 3 + 1)
"%s: any worker tried to consume from splitter: %*lu\n"
"%s: any worker stalled : %*lu\n"
"%s: muxer tried to consume from workers : %*lu\n"
"%s: muxer stalled : %*lu\n"
"%s: splitter tried to consume from muxer : %*lu\n"
"%s: splitter stalled : %*lu\n",
pname, FW, s2w_q.av_or_eof.ccount,
pname, FW, s2w_q.av_or_eof.wcount,
pname, FW, w2m_q.av_or_exit.ccount,
pname, FW, w2m_q.av_or_exit.wcount,
pname, FW, m2s_q.av.ccount,
pname, FW, m2s_q.av.wcount)
# undef FW
#endif
----^----
Of course I later removed the "#if 0" block (but not the leading
comment). I was shocked because I always considered OSF/1 a reference
implementation of the SUS. Of course I may have botched up the format
string, but I tried to verify it by re-reading the quoted paragraphs
many times, it worked on glibc flawlessly, and gcc's -Wformat=2 didn't
complain.
lacos