Fix money type USE_LOCALE support at least for default "C" locale.
authorThomas G. Lockhart
Mon, 2 Mar 1998 00:13:36 +0000 (00:13 +0000)
committerThomas G. Lockhart
Mon, 2 Mar 1998 00:13:36 +0000 (00:13 +0000)
Still has questionable code for some locale-specific strings.

src/backend/utils/adt/cash.c

index e9e3a971b49ac6c92e7fe2391da85fc9385603db..90f92bd24faf906799e007d1a54dafaf988e516b 100644 (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 
@@ -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];