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 (second try)


I finally found time to complete this patch.

[Ulrich Drepper, 2003-09-14]
> I don't see a reason for this complicated macro.  The international
> value for most fields is always defined.

Right.  I found the code setting the international values in
localedef.  Thanks for pointing it out.

> The only exception is int_frac_digits.  And here the value -1 is
> used (not CHAR_MAX) and it has a legitimate meaning.

Changed.

> So the whole macro expansion should be
> 
>   *_NL_CURRENT (category, int_format ? int_item : item)
> 
> Drop the 'value' parameter in the macro, and make the assignment
> explicit in the code.

Done.

> And drop the extra { } around single statements, they just make the
> code less readable.

Done.

This patch is related to the patch to make sure the international
currency name check in localedef only check the name of the currency
and not the white space as well,
<URL:http://sources.redhat.com/ml/libc-alpha/2003-11/msg00126.html>.

Both patches exposes several bugs in the current locales, but it also
make it possible to fix some existing bugs.  For example, in no_NO it
is currently impossible to represent the correct string "NOK 1,23".
The extra space is inserted and the text end up with "NOK 1,23".
Also, this patch make it possible to represent different currency name
placing in the same locale, ie "$ 1" and "1 USD".

I have a test case for this as well, initially submitted as
<URL:http://sources.redhat.com/ml/libc-alpha/2003-06/msg00257.html>.
The test results in this patch is clearly wrong, and this patch make
it possible to correct the results.

Would you like one big patch fixing all of these things, or do you
want to take them piece by piece?

2003-11-23  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	23 Nov 2003 09:07:15 -0000
@@ -128,6 +128,7 @@ __strfmon_l (char *s, size_t maxsize, __
 	__long_double_t ldbl;
       }
       fpnum;
+      int int_format;
       int print_curr_symbol;
       int left_prec;
       int left_pad;
@@ -172,6 +173,7 @@ __strfmon_l (char *s, size_t maxsize, __
 	}
 
       /* 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 +235,6 @@ __strfmon_l (char *s, size_t maxsize, __
 	  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 +302,25 @@ __strfmon_l (char *s, size_t maxsize, __
       /* 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 +328,20 @@ __strfmon_l (char *s, size_t maxsize, __
 	  return -1;
 	}
 
+      /* 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, int_format ? INT_P_SIGN_POSN : P_SIGN_POSN);
+      if (n_sign_posn == -1)
+	n_sign_posn = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SIGN_POSN : N_SIGN_POSN);
+
+      if (right_prec == -1)
+	{
+	  right_prec = *_NL_CURRENT (LC_MONETARY, int_format ? INT_FRAC_DIGITS : FRAC_DIGITS);
+	  if (right_prec == -1)
+	    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 +374,27 @@ __strfmon_l (char *s, size_t maxsize, __
 	     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);
+	  cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_CS_PRECEDES : N_CS_PRECEDES);
+	  sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SEP_BY_SPACE : 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);
+	  other_cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_CS_PRECEDES : P_CS_PRECEDES);
+	  other_sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SEP_BY_SPACE : 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);
+	  cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_CS_PRECEDES : P_CS_PRECEDES);
+	  sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SEP_BY_SPACE : 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);
+	  other_cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_CS_PRECEDES : N_CS_PRECEDES);
+	  other_sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SEP_BY_SPACE : 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]