diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c
index e9e3a971b49ac6c92e7fe2391da85fc9385603db..90f92bd24faf906799e007d1a54dafaf988e516b 100644
--- a/src/backend/utils/adt/cash.c
+++ b/src/backend/utils/adt/cash.c
@@ -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];