This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
patch: Correct formatting of internatinal currency
- From: Petter Reinholdtsen <pere at hungry dot com>
- To: libc-alpha at sources dot redhat dot com
- Date: Sun, 14 Sep 2003 20:00:49 +0200
- Subject: 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;
}