]> granicus.if.org Git - postgresql/commitdiff
Fix money type USE_LOCALE support at least for default "C" locale.
authorThomas G. Lockhart <lockhart@fourpalms.org>
Mon, 2 Mar 1998 00:13:36 +0000 (00:13 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
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 <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];