提交 75c147e7 编写于 作者: T Tom Lane

Modify locale code to defend against possibility that it was compiled

with an -fsigned-char/-funsigned-char setting opposite to that of libc,
thus breaking the convention that 'undefined' values returned by
localeconv() are represented by CHAR_MAX.  It is sheer stupidity that
gcc even has such a switch --- it's just as bad as the structure-packing
control switches offered by the more brain-dead PC compilers --- and
as for the behavior of Linux distribution vendors who set RPM_OPT_FLAGS
differently from the way they built libc, well, words fail me...
上级 aa21da20
......@@ -9,7 +9,7 @@
* workings can be found in the book "Software Solutions in C" by
* Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
*
* $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.45 2000/08/03 16:34:22 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.46 2000/11/18 03:55:51 tgl Exp $
*/
#include <limits.h>
......@@ -91,9 +91,19 @@ cash_in(PG_FUNCTION_ARGS)
if (lconvert == NULL)
lconvert = localeconv();
/* frac_digits in the C locale seems to return CHAR_MAX */
/* best guess is 2 in this case I think */
fpoint = ((lconvert->frac_digits != (char)CHAR_MAX) ? lconvert->frac_digits : 2); /* int_frac_digits? */
/*
* frac_digits will be CHAR_MAX in some locales, notably C. However,
* just testing for == CHAR_MAX is risky, because of compilers like
* gcc that "helpfully" let you alter the platform-standard definition
* of whether char is signed or not. If we are so unfortunate as to
* get compiled with a nonstandard -fsigned-char or -funsigned-char
* switch, then our idea of CHAR_MAX will not agree with libc's.
* The safest course is not to test for CHAR_MAX at all, but to impose
* a range check for plausible frac_digits values.
*/
fpoint = lconvert->frac_digits;
if (fpoint < 0 || fpoint > 10)
fpoint = 2; /* best guess in this case, I think */
dsymbol = ((*lconvert->mon_decimal_point != '\0') ? *lconvert->mon_decimal_point : '.');
ssymbol = ((*lconvert->mon_thousands_sep != '\0') ? *lconvert->mon_thousands_sep : ',');
......@@ -225,9 +235,9 @@ cash_out(PG_FUNCTION_ARGS)
int count = LAST_DIGIT;
int point_pos;
int comma_position = 0;
char mon_group,
comma,
points;
int points,
mon_group;
char comma;
char *csymbol,
dsymbol,
*nsymbol;
......@@ -237,32 +247,36 @@ cash_out(PG_FUNCTION_ARGS)
if (lconvert == NULL)
lconvert = localeconv();
/* see comments about frac_digits in cash_in() */
points = lconvert->frac_digits;
if (points < 0 || points > 10)
points = 2; /* best guess in this case, I think */
/*
* As with frac_digits, must apply a range check to mon_grouping
* to avoid being fooled by variant CHAR_MAX values.
*/
mon_group = *lconvert->mon_grouping;
if (mon_group <= 0 || mon_group > 6)
mon_group = 3;
comma = ((*lconvert->mon_thousands_sep != '\0') ? *lconvert->mon_thousands_sep : ',');
/* frac_digits in the C locale seems to return CHAR_MAX */
/* best guess is 2 in this case I think */
points = ((lconvert->frac_digits != (char)CHAR_MAX) ? lconvert->frac_digits : 2); /* int_frac_digits? */
convention = lconvert->n_sign_posn;
dsymbol = ((*lconvert->mon_decimal_point != '\0') ? *lconvert->mon_decimal_point : '.');
csymbol = ((*lconvert->currency_symbol != '\0') ? lconvert->currency_symbol : "$");
nsymbol = ((*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-");
#else
points = 2;
mon_group = 3;
comma = ',';
csymbol = "$";
convention = 0;
dsymbol = '.';
csymbol = "$";
nsymbol = "-";
points = 2;
convention = 0;
#endif
point_pos = LAST_DIGIT - points;
/* We're playing a little fast and loose with this. Shoot me. */
/* Not me, that was the other guy. Haven't fixed it yet - thomas */
if (!mon_group || mon_group == (char)CHAR_MAX)
mon_group = 3;
/* allow more than three decimal points and separate them */
if (comma)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册