I downloaded ast-ksh.2006-06-30.tgz and INIT.2006-06-30.tgz this afternoon
and traced the source with C and en_US locales at Solaris 10 and found
the reason is due to there is a bug in strtold() at lib/libast/sfio/sfstrtof.h
especially the line 362 where it assumes that the thousand separator
character of the current locale is a valid part of a double number regardless
of its position, i.e., it assumes that the comma argument separator at
the pow(1.0,Inf) expression as a part of the first input argument, "1.0":
n = 0;
m = 0;
for (;;)
{
if (c >= '0' && c <= '9')
{
digits++;
n = (n << 3) + (n << 1) + (c - '0');
if (n >= ((~((S2F_batch)0)) / 10) && part <
elementsof(p
arts))
{
parts[part].batch = n;
n = 0;
parts[part].digits = digits;
part++;
}
}
else if (m && (digits - m) != 3)
break;
else if (c == decimal)
{
decimal = -1;
m = 0;
fraction = digits;
}
else if (c != thousand) /* <--<<< */
break;
else if (!(m = digits))
break;
c = GET(s);
}
and thus the above consumes the ',' and move the expression string pointer
one more character than necessary. The locales that don't have this issue
would be the ones that the thousand separater is defined in their
locale database as -1. For instance:
$ env LC_ALL=C locale -k thousands_sep
thousands_sep=""
$ env LC_ALL=en_US.UTF-8 locale -k thousands_sep
thousands_sep=""
$ env LC_ALL=ja_JP.UTF-8 locale -k thousands_sep
thousands_sep=","
$ env LC_ALL=de_DE.UTF-8 locale -k thousands_sep
thousands_sep="."
$
And so if you replace the line 362 to the following expression, then,
the problem appears go away:
else if (c != thousand || (c == thousand && decimal == -1))
For instance:
$ export LC_ALL=de_DE.UTF-8 ; echo $((pow(1,0,Inf)))
NaN
$ export LC_ALL=ja_JP.UTF-8 ; echo $((pow(1.0,Inf)))
NaN
Ienup
Roland Mainz wrote at 07/15/06 14:28:
> Hi!
>
> ----
>
> I just got some feedback about what seems to be a locale-specific bug in
> ksh93:
>
> Trying the following in ksh93q (SuSE Linux 10.0) ...
> -- snip --
> #!/bin/ksh
> (env - ksh -x -c '( echo $(( pow(1.0,Inf) )) )')
> (env - ksh -x -c '(export LC_ALL=en_US.UTF-8 ; echo $(( pow(1.0,Inf)
> )) )')
> (env - ksh -x -c '(export LC_ALL=ja_JP.UTF-8 ; echo $(( pow(1.0,Inf)
> )) )')
> (env - ksh -x -c '(export LC_ALL=de_DE.UTF-8 ; echo $(( pow(1.0,Inf)
> )) )')
> (env - ksh -x -c '(export LC_ALL=de_DE.ISO8859-15 ; echo $((
> pow(1.0,Inf) )) )')
> (env - ksh -x -c '(export LC_ALL=C ; echo $(( pow(1.0,Inf) )) )')
> (env - ksh -x -c '(export LC_ALL=en_US ; echo $(( pow(1.0,Inf) ))
> )')
> -- snip --
> results in
> -- snip --
> + echo 1
> 1
> + LC_ALL=en_US.UTF-8
> + export LC_ALL
> ksh: line 1: pow(1.0,Inf) : arithmetic syntax error
> + LC_ALL=ja_JP.UTF-8
> + export LC_ALL
> ksh: line 1: pow(1.0,Inf) : arithmetic syntax error
> + LC_ALL=de_DE.UTF-8
> + export LC_ALL
> ksh: line 1: pow(1.0,Inf) : arithmetic syntax error
> + LC_ALL=de_DE.ISO8859-15
> + export LC_ALL
> + echo 1
> 1
> + LC_ALL=C
> + export LC_ALL
> + echo 1
> 1
> + LC_ALL=en_US
> + export LC_ALL
> ksh: line 1: pow(1.0,Inf) : arithmetic syntax error
> -- snip --
>
> I tried the same with ksh93r+_20060630 in the ksh93-integration
> prototype002 tree on Solaris x86 B37
> -- snip --
> (env - LD_LIBRARY_PATH=$ROOT/lib i386/ksh -x -c
> '( echo $(( pow(1.0,Inf) )) )')
> (env - LD_LIBRARY_PATH=$ROOT/lib i386/ksh -x -c '(export
> LC_ALL=en_US.UTF-8 ; echo $(( pow(1.0,Inf) )) )')
> (env - LD_LIBRARY_PATH=$ROOT/lib i386/ksh -x -c '(export
> LC_ALL=ja_JP.UTF-8 ; echo $(( pow(1.0,Inf) )) )')
> (env - LD_LIBRARY_PATH=$ROOT/lib i386/ksh -x -c '(export
> LC_ALL=de_DE.UTF-8 ; echo $(( pow(1.0,Inf) )) )')
> (env - LD_LIBRARY_PATH=$ROOT/lib i386/ksh -x -c '(export
> LC_ALL=de_DE.ISO8859-15 ; echo $(( pow(1.0,Inf) )) )')
> (env - LD_LIBRARY_PATH=$ROOT/lib i386/ksh -x -c '(export
> LC_ALL=C ; echo $(( pow(1.0,Inf) )) )')
> (env - LD_LIBRARY_PATH=$ROOT/lib i386/ksh -x -c '(export
> LC_ALL=en_US ; echo $(( pow(1.0,Inf) )) )')
> -- snip --
> and got the following results
> -- snip --
> + echo 1
> 1
> + LC_ALL=en_US.UTF-8
> + export LC_ALL
> + echo 1
> 1
> + LC_ALL=ja_JP.UTF-8
> + export LC_ALL
> i386/ksh: line 1: pow(1.0,Inf) : arithmetic syntax error
> + LC_ALL=de_DE.UTF-8
> + export LC_ALL
> i386/ksh: line 1: pow(1.0,Inf) : arithmetic syntax error
> + LC_ALL=de_DE.ISO8859-15
> + export LC_ALL
> i386/ksh: line 1: pow(1.0,Inf) : arithmetic syntax error
> + LC_ALL=C
> + export LC_ALL
> + echo 1
> 1
> + LC_ALL=en_US
> + export LC_ALL
> i386/ksh: line 1: pow(1.0,Inf) : arithmetic syntax error
> -- snip --
>
> Something is going wrong here (CC:'ing the i18n-discuss at opensolaris.org
> in the hope that Ienup may know what may cause this...) ... any ideas
> where this bug may hide ?
>
> ----
>
> Bye,
> Roland
>