Fix money type USE_LOCALE support at least for default "C" locale.

Still has questionable code for some locale-specific strings.
This commit is contained in:
Thomas G. Lockhart 1998-03-02 00:13:36 +00:00
parent bb63cb8f79
commit 77ac40d73e
1 changed files with 53 additions and 26 deletions

View File

@ -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.22 1998/02/26 04:36:53 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.23 1998/03/02 00:13:36 thomas Exp $
*/
#include <stdio.h>
@ -34,7 +34,6 @@ static const char *num_word(Cash value);
#ifdef USE_LOCALE
static struct lconv *lconvert = NULL;
#endif
/* cash_in()
@ -46,6 +45,8 @@ static struct lconv *lconvert = NULL;
* XXX HACK It looks as though some of the symbols for
* monetary values returned by localeconv() can be multiple
* bytes/characters. This code assumes one byte only. - tgl 97/04/14
* XXX UNHACK Allow the currency symbol to be multi-byte.
* - thomas 1998-03-01
*/
Cash *
cash_in(const char *str)
@ -58,11 +59,11 @@ cash_in(const char *str)
int seen_dot = 0;
const char *s = str;
int fpoint;
char *csymbol;
char dsymbol,
ssymbol,
psymbol,
nsymbol,
csymbol;
*nsymbol;
#ifdef USE_LOCALE
#ifdef CASHDEBUG
@ -76,33 +77,45 @@ cash_in(const char *str)
/* best guess is 2 in this case I think */
fpoint = ((lconvert->frac_digits != CHAR_MAX) ? lconvert->frac_digits : 2); /* int_frac_digits? */
dsymbol = *lconvert->mon_decimal_point;
ssymbol = *lconvert->mon_thousands_sep;
csymbol = *lconvert->currency_symbol;
psymbol = *lconvert->positive_sign;
nsymbol = *lconvert->negative_sign;
dsymbol = ((*lconvert->mon_decimal_point != '\0')? *lconvert->mon_decimal_point: '.');
ssymbol = ((*lconvert->mon_thousands_sep != '\0')? *lconvert->mon_thousands_sep: ',');
csymbol = ((*lconvert->currency_symbol != '\0')? lconvert->currency_symbol: "$");
psymbol = ((*lconvert->positive_sign != '\0')? *lconvert->positive_sign: '+');
nsymbol = ((*lconvert->negative_sign != '\0')? lconvert->negative_sign: "-");
#else
fpoint = 2;
dsymbol = '.';
ssymbol = ',';
csymbol = '$';
csymbol = "$";
psymbol = '+';
nsymbol = '-';
nsymbol = "-";
#endif
#ifdef CASHDEBUG
printf("cashin- precision %d; decimal %c; thousands %c; currency %c; positive %c; negative %c\n",
fpoint, dsymbol, ssymbol, csymbol, psymbol, nsymbol);
printf( "cashin- precision '%d'; decimal '%c'; thousands '%c'; currency '%s'; positive '%c'; negative '%s'\n",
fpoint, dsymbol, ssymbol, csymbol, psymbol, nsymbol);
#endif
/* we need to add all sorts of checking here. For now just */
/* strip all leading whitespace and any leading dollar sign */
while (isspace(*s) || *s == csymbol)
s++;
/* strip all leading whitespace and any leading currency symbol */
while (isspace(*s)) s++;
if (strncmp(s,csymbol,strlen(csymbol)) == 0) s += strlen(csymbol);
#ifdef CASHDEBUG
printf( "cashin- string is '%s'\n", s);
#endif
/* a leading minus or paren signifies a negative number */
/* again, better heuristics needed */
if (*s == nsymbol || *s == '(')
if (strncmp(s,nsymbol,strlen(nsymbol)) == 0)
{
sgn = -1;
s += strlen(nsymbol);
#ifdef CASHDEBUG
printf( "cashin- negative symbol; string is '%s'\n", s);
#endif
}
else if (*s == '(')
{
sgn = -1;
s++;
@ -113,8 +126,16 @@ cash_in(const char *str)
s++;
}
while (isspace(*s) || *s == csymbol)
s++;
#ifdef CASHDEBUG
printf( "cashin- string is '%s'\n", s);
#endif
while (isspace(*s)) s++;
if (strncmp(s,csymbol,strlen(csymbol)) == 0) s += strlen(csymbol);
#ifdef CASHDEBUG
printf( "cashin- string is '%s'\n", s);
#endif
for (;; s++)
{
@ -164,6 +185,10 @@ cash_in(const char *str)
*result = (value * sgn);
#ifdef CASHDEBUG
printf( "cashin- result is %d\n", *result);
#endif
return (result);
} /* cash_in() */
@ -186,7 +211,7 @@ cash_out(Cash *in_value)
char mon_group,
comma,
points;
char csymbol,
char *csymbol,
dsymbol,
*nsymbol;
char convention;
@ -196,18 +221,18 @@ cash_out(Cash *in_value)
lconvert = localeconv();
mon_group = *lconvert->mon_grouping;
comma = *lconvert->mon_thousands_sep;
csymbol = *lconvert->currency_symbol;
dsymbol = *lconvert->mon_decimal_point;
nsymbol = lconvert->negative_sign;
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_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
mon_group = 3;
comma = ',';
csymbol = '$';
csymbol = "$";
dsymbol = '.';
nsymbol = "-";
points = 2;
@ -217,6 +242,7 @@ cash_out(Cash *in_value)
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_MAX)
mon_group = 3;
@ -249,7 +275,8 @@ cash_out(Cash *in_value)
value /= 10;
}
buf[count] = csymbol;
strncpy((buf+count-strlen(csymbol)+1),csymbol,strlen(csymbol));
count -= strlen(csymbol)-1;
if (buf[LAST_DIGIT] == ',')
buf[LAST_DIGIT] = buf[LAST_PAREN];