Commit 77ac40d7 authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

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

Still has questionable code for some locale-specific strings.
parent bb63cb8f
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* workings can be found in the book "Software Solutions in C" by * workings can be found in the book "Software Solutions in C" by
* Dale Schumacher, Academic Press, ISBN: 0-12-632360-7. * 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> #include <stdio.h>
...@@ -34,7 +34,6 @@ static const char *num_word(Cash value); ...@@ -34,7 +34,6 @@ static const char *num_word(Cash value);
#ifdef USE_LOCALE #ifdef USE_LOCALE
static struct lconv *lconvert = NULL; static struct lconv *lconvert = NULL;
#endif #endif
/* cash_in() /* cash_in()
...@@ -46,6 +45,8 @@ static struct lconv *lconvert = NULL; ...@@ -46,6 +45,8 @@ static struct lconv *lconvert = NULL;
* XXX HACK It looks as though some of the symbols for * XXX HACK It looks as though some of the symbols for
* monetary values returned by localeconv() can be multiple * monetary values returned by localeconv() can be multiple
* bytes/characters. This code assumes one byte only. - tgl 97/04/14 * 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 *
cash_in(const char *str) cash_in(const char *str)
...@@ -58,11 +59,11 @@ cash_in(const char *str) ...@@ -58,11 +59,11 @@ cash_in(const char *str)
int seen_dot = 0; int seen_dot = 0;
const char *s = str; const char *s = str;
int fpoint; int fpoint;
char *csymbol;
char dsymbol, char dsymbol,
ssymbol, ssymbol,
psymbol, psymbol,
nsymbol, *nsymbol;
csymbol;
#ifdef USE_LOCALE #ifdef USE_LOCALE
#ifdef CASHDEBUG #ifdef CASHDEBUG
...@@ -76,33 +77,45 @@ cash_in(const char *str) ...@@ -76,33 +77,45 @@ cash_in(const char *str)
/* best guess is 2 in this case I think */ /* best guess is 2 in this case I think */
fpoint = ((lconvert->frac_digits != CHAR_MAX) ? lconvert->frac_digits : 2); /* int_frac_digits? */ fpoint = ((lconvert->frac_digits != CHAR_MAX) ? lconvert->frac_digits : 2); /* int_frac_digits? */
dsymbol = *lconvert->mon_decimal_point; dsymbol = ((*lconvert->mon_decimal_point != '\0')? *lconvert->mon_decimal_point: '.');
ssymbol = *lconvert->mon_thousands_sep; ssymbol = ((*lconvert->mon_thousands_sep != '\0')? *lconvert->mon_thousands_sep: ',');
csymbol = *lconvert->currency_symbol; csymbol = ((*lconvert->currency_symbol != '\0')? lconvert->currency_symbol: "$");
psymbol = *lconvert->positive_sign; psymbol = ((*lconvert->positive_sign != '\0')? *lconvert->positive_sign: '+');
nsymbol = *lconvert->negative_sign; nsymbol = ((*lconvert->negative_sign != '\0')? lconvert->negative_sign: "-");
#else #else
fpoint = 2; fpoint = 2;
dsymbol = '.'; dsymbol = '.';
ssymbol = ','; ssymbol = ',';
csymbol = '$'; csymbol = "$";
psymbol = '+'; psymbol = '+';
nsymbol = '-'; nsymbol = "-";
#endif #endif
#ifdef CASHDEBUG #ifdef CASHDEBUG
printf("cashin- precision %d; decimal %c; thousands %c; currency %c; positive %c; negative %c\n", printf( "cashin- precision '%d'; decimal '%c'; thousands '%c'; currency '%s'; positive '%c'; negative '%s'\n",
fpoint, dsymbol, ssymbol, csymbol, psymbol, nsymbol); fpoint, dsymbol, ssymbol, csymbol, psymbol, nsymbol);
#endif #endif
/* we need to add all sorts of checking here. For now just */ /* we need to add all sorts of checking here. For now just */
/* strip all leading whitespace and any leading dollar sign */ /* strip all leading whitespace and any leading currency symbol */
while (isspace(*s) || *s == csymbol) while (isspace(*s)) 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 */ /* a leading minus or paren signifies a negative number */
/* again, better heuristics needed */ /* 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; sgn = -1;
s++; s++;
...@@ -113,8 +126,16 @@ cash_in(const char *str) ...@@ -113,8 +126,16 @@ cash_in(const char *str)
s++; s++;
} }
while (isspace(*s) || *s == csymbol) #ifdef CASHDEBUG
s++; 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++) for (;; s++)
{ {
...@@ -164,6 +185,10 @@ cash_in(const char *str) ...@@ -164,6 +185,10 @@ cash_in(const char *str)
*result = (value * sgn); *result = (value * sgn);
#ifdef CASHDEBUG
printf( "cashin- result is %d\n", *result);
#endif
return (result); return (result);
} /* cash_in() */ } /* cash_in() */
...@@ -186,7 +211,7 @@ cash_out(Cash *in_value) ...@@ -186,7 +211,7 @@ cash_out(Cash *in_value)
char mon_group, char mon_group,
comma, comma,
points; points;
char csymbol, char *csymbol,
dsymbol, dsymbol,
*nsymbol; *nsymbol;
char convention; char convention;
...@@ -196,18 +221,18 @@ cash_out(Cash *in_value) ...@@ -196,18 +221,18 @@ cash_out(Cash *in_value)
lconvert = localeconv(); lconvert = localeconv();
mon_group = *lconvert->mon_grouping; mon_group = *lconvert->mon_grouping;
comma = *lconvert->mon_thousands_sep; comma = ((*lconvert->mon_thousands_sep != '\0')? *lconvert->mon_thousands_sep: ',');
csymbol = *lconvert->currency_symbol;
dsymbol = *lconvert->mon_decimal_point;
nsymbol = lconvert->negative_sign;
/* frac_digits in the C locale seems to return CHAR_MAX */ /* frac_digits in the C locale seems to return CHAR_MAX */
/* best guess is 2 in this case I think */ /* best guess is 2 in this case I think */
points = ((lconvert->frac_digits != CHAR_MAX) ? lconvert->frac_digits : 2); /* int_frac_digits? */ points = ((lconvert->frac_digits != CHAR_MAX) ? lconvert->frac_digits : 2); /* int_frac_digits? */
convention = lconvert->n_sign_posn; 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 #else
mon_group = 3; mon_group = 3;
comma = ','; comma = ',';
csymbol = '$'; csymbol = "$";
dsymbol = '.'; dsymbol = '.';
nsymbol = "-"; nsymbol = "-";
points = 2; points = 2;
...@@ -217,6 +242,7 @@ cash_out(Cash *in_value) ...@@ -217,6 +242,7 @@ cash_out(Cash *in_value)
point_pos = LAST_DIGIT - points; point_pos = LAST_DIGIT - points;
/* We're playing a little fast and loose with this. Shoot me. */ /* 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) if (!mon_group || mon_group == CHAR_MAX)
mon_group = 3; mon_group = 3;
...@@ -249,7 +275,8 @@ cash_out(Cash *in_value) ...@@ -249,7 +275,8 @@ cash_out(Cash *in_value)
value /= 10; value /= 10;
} }
buf[count] = csymbol; strncpy((buf+count-strlen(csymbol)+1),csymbol,strlen(csymbol));
count -= strlen(csymbol)-1;
if (buf[LAST_DIGIT] == ',') if (buf[LAST_DIGIT] == ',')
buf[LAST_DIGIT] = buf[LAST_PAREN]; buf[LAST_DIGIT] = buf[LAST_PAREN];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment