=item *
+The printf and sprintf now support parameter reordering using the
+C<%\d+\$> and C<*\d+\$> syntaxes.
+
+=item *
+
prototype(\&) is now available.
=item *
h interpret integer as C type "short" or "unsigned short"
If no flags, interpret integer as C type "int" or "unsigned"
+Perl supports parameter ordering, in other words, fetching the
+parameters in some explicitly specified "random" ordering as opposed
+to the default implicit sequential ordering. The syntax is, instead
+of the C<%> and C<*>, to use C<%>I<digits>C<$> and C<*>I<digits>C<$>,
+where the I<digits> is the wanted index, from one upwards. For example:
+
+ printf "%2\$d %1\$d\n", 12, 34; # will print "34 12\n"
+ printf "%*2\$d\n", 12, 3; # will print " 12\n"
+
+Note that using the reordering syntax does not interfere with the usual
+implicit sequential fetching of the parameters:
+
+ printf "%2\$d %d\n", 12, 34; # will print "34 12\n"
+ printf "%2\$d %d %d\n", 12, 34; # will print "34 12 34\n"
+ printf "%3\$d %d %d\n", 12, 34, 56; # will print "56 12 34\n"
+ printf "%2\$*3\$d %d\n", 12, 34, 3; # will print " 34 12\n"
+ printf "%*3\$2\$d %d\n", 12, 34, 3; # will print " 34 12\n"
+
There are also two Perl-specific flags:
- V interpret integer as Perl's standard integer type
- v interpret string as a vector of integers, output as
- numbers separated either by dots, or by an arbitrary
- string received from the argument list when the flag
- is preceded by C<*>
+ V interpret integer as Perl's standard integer type
+ v interpret string as a vector of integers, output as
+ numbers separated either by dots, or by an arbitrary
+ string received from the argument list when the flag
+ is preceded by C<*>
Where a number would appear in the flags, an asterisk (C<*>) may be
used instead, in which case Perl uses the next item in the parameter
bool has_precis = FALSE;
STRLEN precis = 0;
bool is_utf = FALSE;
-
+
char esignbuf[4];
U8 utf8buf[UTF8_MAXLEN];
STRLEN esignlen = 0;
STRLEN gap;
char *dotstr = ".";
STRLEN dotstrlen = 1;
+ I32 epix = 0; /* explicit parameter index */
+ I32 ewix = 0; /* explicit width index */
+ bool asterisk = FALSE;
for (q = p; q < patend && *q != '%'; ++q) ;
if (q > p) {
/* WIDTH */
+ scanwidth:
+
+ if (*q == '*') {
+ if (asterisk)
+ goto unknown;
+ asterisk = TRUE;
+ q++;
+ }
+
switch (*q) {
case '1': case '2': case '3':
case '4': case '5': case '6':
width = 0;
while (isDIGIT(*q))
width = width * 10 + (*q++ - '0');
- break;
+ if (*q == '$') {
+ if (asterisk && ewix == 0) {
+ ewix = width;
+ width = 0;
+ q++;
+ goto scanwidth;
+ } else if (epix == 0) {
+ epix = width;
+ width = 0;
+ q++;
+ goto scanwidth;
+ } else
+ goto unknown;
+ }
+ }
- case '*':
+ if (asterisk) {
if (args)
i = va_arg(*args, int);
else
- i = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
+ i = (ewix ? ewix <= svmax : svix < svmax) ?
+ SvIVx(svargs[ewix ? ewix-1 : svix++]) : 0;
left |= (i < 0);
width = (i < 0) ? -i : i;
- q++;
- break;
}
/* PRECISION */
if (args)
i = va_arg(*args, int);
else
- i = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
+ i = (ewix ? ewix <= svmax : svix < svmax)
+ ? SvIVx(svargs[ewix ? ewix-1 : svix++]) : 0;
precis = (i < 0) ? 0 : i;
q++;
}
vecstr = (U8*)SvPVx(vecsv,veclen);
utf = DO_UTF8(vecsv);
}
- else if (svix < svmax) {
- vecsv = svargs[svix++];
+ else if (epix ? epix <= svmax : svix < svmax) {
+ vecsv = svargs[epix ? epix-1 : svix++];
vecstr = (U8*)SvPVx(vecsv,veclen);
utf = DO_UTF8(vecsv);
}
if (args)
uv = va_arg(*args, int);
else
- uv = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
+ uv = (epix ? epix <= svmax : svix < svmax) ?
+ SvIVx(svargs[epix ? epix-1 : svix++]) : 0;
if ((uv > 255 || (uv > 127 && SvUTF8(sv))) && !IN_BYTE) {
eptr = (char*)utf8buf;
elen = uv_to_utf8((U8*)eptr, uv) - utf8buf;
elen = sizeof nullstr - 1;
}
}
- else if (svix < svmax) {
- argsv = svargs[svix++];
+ else if (epix ? epix <= svmax : svix < svmax) {
+ argsv = svargs[epix ? epix-1 : svix++];
eptr = SvPVx(argsv, elen);
if (DO_UTF8(argsv)) {
if (has_precis && precis < elen) {
if (args)
uv = PTR2UV(va_arg(*args, void*));
else
- uv = (svix < svmax) ? PTR2UV(svargs[svix++]) : 0;
+ uv = (epix ? epix <= svmax : svix < svmax) ?
+ PTR2UV(svargs[epix ? epix-1 : svix++]) : 0;
base = 16;
goto integer;
}
}
else {
- iv = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
+ iv = (epix ? epix <= svmax : svix < svmax) ?
+ SvIVx(svargs[epix ? epix-1 : svix++]) : 0;
switch (intsize) {
case 'h': iv = (short)iv; break;
default: break;
}
}
else {
- uv = (svix < svmax) ? SvUVx(svargs[svix++]) : 0;
+ uv = (epix ? epix <= svmax : svix < svmax) ?
+ SvUVx(svargs[epix ? epix-1 : svix++]) : 0;
switch (intsize) {
case 'h': uv = (unsigned short)uv; break;
default: break;
if (args)
nv = va_arg(*args, NV);
else
- nv = (svix < svmax) ? SvNVx(svargs[svix++]) : 0.0;
+ nv = (epix ? epix <= svmax : svix < svmax) ?
+ SvNVx(svargs[epix ? epix-1 : svix++]) : 0.0;
need = 0;
if (c != 'e' && c != 'E') {
#endif
}
}
- else if (svix < svmax)
- sv_setuv_mg(svargs[svix++], (UV)i);
+ else if (epix ? epix <= svmax : svix < svmax)
+ sv_setuv_mg(svargs[epix ? epix-1 : svix++], (UV)i);
continue; /* not "break" */
/* UNKNOWN */
>%0*x< >[-10, ,2**32-1]< >ffffffff <
>%y< >''< >%y INVALID<
>%z< >''< >%z INVALID<
+>%2$d %1$d< >[12, 34]< >34 12<
+>%*2$d< >[12, 3]< > 12<
+>%2$d %d< >[12, 34]< >34 12<
+>%2$d %d %d< >[12, 34]< >34 12 34<
+>%3$d %d %d< >[12, 34, 56]< >56 12 34<
+>%2$*3$d %d< >[12, 34, 3]< > 34 12<
+>%*3$2$d %d< >[12, 34, 3]< > 34 12<
+>%2$d< >12< >0<
+>%0$d< >12< >%0$d INVALID<
+>%1$$d< >12< >%1$$d INVALID<
+>%1$1$d< >12< >%1$1$d INVALID<
+>%*2$*2$d< >[12, 3]< >%*2$*2$d INVALID<
+>%*2*2$d< >[12, 3]< >%*2*2$d INVALID<