* 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>
#ifdef USE_LOCALE
static struct lconv *lconvert = NULL;
-
#endif
/* cash_in()
* 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)
int seen_dot = 0;
const char *s = str;
int fpoint;
+ char *csymbol;
char dsymbol,
ssymbol,
psymbol,
- nsymbol,
- csymbol;
+ *nsymbol;
#ifdef USE_LOCALE
#ifdef CASHDEBUG
/* 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++;
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++)
{
*result = (value * sgn);
+#ifdef CASHDEBUG
+printf( "cashin- result is %d\n", *result);
+#endif
+
return (result);
} /* cash_in() */
char mon_group,
comma,
points;
- char csymbol,
+ char *csymbol,
dsymbol,
*nsymbol;
char convention;
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;
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;
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];