This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

patch: Correct formatting of internatinal currency


This patch fixes the formatting of international currency, making it
possible to use the correct formatting for locales where the "normal"
and the international currency symbol should have different position.
At the moment, the values for international currency formatting is
ignored.  The default will still be the normal symbols, so for locales
without int_* values, the output should stay the same.  For locales
with int_* values that was previously ignored, the output might change
(for better or for worse, of course :).

Please include it in the next version of glibc.

When this patch is included in CVS, I'll send a new patch updating the
tests to document that this actually work.  I'm still working on this
one.


2003-09-14  Petter Reinholdtsen  <pere@hungry.com>

	* stdlib/strfmon.c: Correct formatting of international currency
	values.  The international currency formatting should prefer the
	int_* values if they are set for a locale, and use the domestic
	values if the int_* values are unset.

Index: stdlib/strfmon.c
===================================================================
RCS file: /cvs/glibc/libc/stdlib/strfmon.c,v
retrieving revision 1.23
diff -u -3 -p -u -r1.23 strfmon.c
--- stdlib/strfmon.c    3 Aug 2002 06:29:57 -0000       1.23
+++ stdlib/strfmon.c    14 Sep 2003 17:52:00 -0000
@@ -74,6 +74,24 @@
   (current->values[_NL_ITEM_INDEX (item)].string)
 #endif
 
+/* Use the value for international currency formatting when formatting
+   international currency if it is set, otherwise fall back to the
+   normal formatting vlaue.  Have to use a macro, as _NL_CURRENT()
+   some times need a variable 'current', and some times not.  A
+   function would be hard to pass arguments to.  */
+#define GET_VALUE(value, category, int_format, item, int_item)               \
+do {                                                                         \
+  value = CHAR_MAX;                                                          \
+  if (int_format)                                                            \
+    {                                                                        \
+      value = *_NL_CURRENT (category, int_item);                             \
+    }                                                                        \
+  if (value == CHAR_MAX)                                                     \
+    {                                                                        \
+      value = *_NL_CURRENT (category, item);                                 \
+    }                                                                        \
+} while (0)
+
 extern int __printf_fp (FILE *, const struct printf_info *,
 			const void *const *);
 libc_hidden_proto (__printf_fp)
@@ -128,6 +146,7 @@
 	__long_double_t ldbl;
       }
       fpnum;
+      int int_format;
       int print_curr_symbol;
       int left_prec;
       int left_pad;
@@ -172,6 +191,7 @@
 	}
 
       /* Defaults for formatting.  */
+      int_format = 0;			/* Use international curr. symbol */
       print_curr_symbol = 1;		/* Print the currency symbol.  */
       left_prec = -1;			/* No left precision specified.  */
       right_prec = -1;			/* No right precision specified.  */
@@ -233,13 +253,6 @@
 	  break;
 	}
 
-      /* If not specified by the format string now find the values for
-	 the format specification.  */
-      if (p_sign_posn == -1)
-	p_sign_posn = *_NL_CURRENT (LC_MONETARY, P_SIGN_POSN);
-      if (n_sign_posn == -1)
-	n_sign_posn = *_NL_CURRENT (LC_MONETARY, N_SIGN_POSN);
-
       if (isdigit (*fmt))
 	{
 	  /* Parse field width.  */
@@ -307,29 +320,25 @@
       /* Handle format specifier.  */
       switch (*fmt++)
 	{
-	case 'i':		/* Use international currency symbol.  */
-	  currency_symbol = _NL_CURRENT (LC_MONETARY, INT_CURR_SYMBOL);
+	case 'i': {		/* Use international currency symbol.  */
+	  const char *int_curr_symbol;
+	  static char symbol[4];
+
+	  int_curr_symbol = _NL_CURRENT (LC_MONETARY, INT_CURR_SYMBOL);
+	  strncpy(symbol, int_curr_symbol, 3);
+	  symbol[3] = '\0';
+
 	  currency_symbol_len = 3;
-	  space_char = currency_symbol[3];
-	  if (right_prec == -1)
-	    {
-	      if (*_NL_CURRENT (LC_MONETARY, INT_FRAC_DIGITS) == CHAR_MAX)
-		right_prec = 2;
-	      else
-		right_prec = *_NL_CURRENT (LC_MONETARY, INT_FRAC_DIGITS);
-	    }
+	  currency_symbol = &symbol[0];
+	  space_char = int_curr_symbol[3];
+	  int_format = 1;
 	  break;
+	}
 	case 'n':		/* Use national currency symbol.  */
 	  currency_symbol = _NL_CURRENT (LC_MONETARY, CURRENCY_SYMBOL);
 	  currency_symbol_len = strlen (currency_symbol);
 	  space_char = ' ';
-	  if (right_prec == -1)
-	    {
-	      if (*_NL_CURRENT (LC_MONETARY, FRAC_DIGITS) == CHAR_MAX)
-		right_prec = 2;
-	      else
-		right_prec = *_NL_CURRENT (LC_MONETARY, FRAC_DIGITS);
-	    }
+	  int_format = 0;
 	  break;
 	default:		/* Any unrecognized format is an error.  */
 	  __set_errno (EINVAL);
@@ -337,6 +346,27 @@
 	  return -1;
 	}
 
+      /* If not specified by the format string now find the values for
+	 the format specification.  */
+      if (p_sign_posn == -1)
+	{
+	  GET_VALUE (p_sign_posn, LC_MONETARY, int_format,
+		     P_SIGN_POSN, INT_P_SIGN_POSN);
+	}
+      if (n_sign_posn == -1)
+	{
+	  GET_VALUE (n_sign_posn, LC_MONETARY, int_format,
+		     N_SIGN_POSN, INT_N_SIGN_POSN);
+	}
+
+      if (right_prec == -1)
+	{
+	  GET_VALUE (right_prec, LC_MONETARY, int_format,
+		     FRAC_DIGITS, INT_FRAC_DIGITS);
+	  if (right_prec == CHAR_MAX)
+	    right_prec = 2;
+	}
+
       /* If we have to print the digits grouped determine how many
 	 extra characters this means.  */
       if (group && left_prec != -1)
@@ -369,27 +399,35 @@
 	     negative sign we use a '-'.  */
 	  if (*sign_string == '\0')
 	    sign_string = (const char *) "-";
-	  cs_precedes = *_NL_CURRENT (LC_MONETARY, N_CS_PRECEDES);
-	  sep_by_space = *_NL_CURRENT (LC_MONETARY, N_SEP_BY_SPACE);
+	  GET_VALUE (cs_precedes, LC_MONETARY, int_format,
+		     N_CS_PRECEDES, INT_N_CS_PRECEDES);
+	  GET_VALUE (sep_by_space, LC_MONETARY, int_format,
+		     N_SEP_BY_SPACE, INT_N_SEP_BY_SPACE);
 	  sign_posn = n_sign_posn;
 
 	  other_sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN);
-	  other_cs_precedes = *_NL_CURRENT (LC_MONETARY, P_CS_PRECEDES);
-	  other_sep_by_space = *_NL_CURRENT (LC_MONETARY, P_SEP_BY_SPACE);
+	  GET_VALUE (other_cs_precedes, LC_MONETARY, int_format,
+		     P_CS_PRECEDES, INT_P_CS_PRECEDES);
+	  GET_VALUE (other_sep_by_space, LC_MONETARY, int_format,
+		     P_SEP_BY_SPACE, INT_P_SEP_BY_SPACE);
 	  other_sign_posn = p_sign_posn;
 	}
       else
 	{
 	  sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN);
-	  cs_precedes = *_NL_CURRENT (LC_MONETARY, P_CS_PRECEDES);
-	  sep_by_space = *_NL_CURRENT (LC_MONETARY, P_SEP_BY_SPACE);
+	  GET_VALUE (cs_precedes, LC_MONETARY, int_format,
+		     P_CS_PRECEDES, INT_P_CS_PRECEDES);
+	  GET_VALUE (sep_by_space, LC_MONETARY, int_format,
+		     P_SEP_BY_SPACE, INT_P_SEP_BY_SPACE);
 	  sign_posn = p_sign_posn;
 
 	  other_sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN);
 	  if (*other_sign_string == '\0')
 	    other_sign_string = (const char *) "-";
-	  other_cs_precedes = *_NL_CURRENT (LC_MONETARY, N_CS_PRECEDES);
-	  other_sep_by_space = *_NL_CURRENT (LC_MONETARY, N_SEP_BY_SPACE);
+	  GET_VALUE (other_cs_precedes, LC_MONETARY, int_format,
+		     N_CS_PRECEDES, INT_N_CS_PRECEDES);
+	  GET_VALUE (other_sep_by_space, LC_MONETARY, int_format,
+		     N_SEP_BY_SPACE, INT_N_SEP_BY_SPACE);
 	  other_sign_posn = n_sign_posn;
 	}
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]