The following issue has been SUBMITTED. ====================================================================== http://austingroupbugs.net/view.php?id=1199 ====================================================================== Reported By: bhaible Assigned To: ====================================================================== Project: 1003.1(2016)/Issue7+TC2 Issue ID: 1199 Category: System Interfaces Type: Error Severity: Editorial Priority: normal Status: New Name: Bruno Haible Organization: GNU User Reference: Section: strfmon Page Number: 2039 to 2043 Line Number: 65327 to 65492 Interp Status: --- Final Accepted Text: ====================================================================== Date Submitted: 2018-08-12 19:23 UTC Last Modified: 2018-08-12 19:23 UTC ====================================================================== Summary: strfmon, if standards compliant, produces highly misleading results Description: The following program shows strfmon results in the C locale: ======================================================================= #include <locale.h> #include <monetary.h> #include <stdio.h> int main () { char buf[80]; printf ("currency = |%s|\n", localeconv()->currency_symbol); printf ("positive sign = |%s|\n", localeconv()->positive_sign); printf ("negative sign = |%s|\n", localeconv()->negative_sign);
strfmon (buf, sizeof (buf), "%^#5.0n", 123.4); printf ("strfmon result for positive value = |%s|\n", buf); strfmon (buf, sizeof (buf), "%^#5.0n", -123.4); printf ("strfmon result for negative value = |%s|\n", buf); strfmon (buf, sizeof (buf), "%.2n", 123.5); printf ("strfmon result with 2 fractional digits: = |%s|\n", buf); } ======================================================================= The result on AIX 7.1 is: currency = || positive sign = || negative sign = || strfmon result for positive value = | 123| strfmon result for negative value = | 123| strfmon result with 2 fractional digits: = |12350| This is POSIX compliant, as far as I can see. However, without a distinction between positive and negative values, and without a visible decimal separator, this behaviour is useless, or even dangerous (if a programmer was not aware of this behaviour and has not worked around it). The result on glibc 2.23 is: currency = || positive sign = || negative sign = || strfmon result for positive value = | 123| strfmon result for negative value = |- 123| strfmon result with 2 fractional digits: = |123.50| This is not POSIX compliant, because in the negative value case, it shows a '-' sign, although localeconv()->negative_sign is the empty string (which is mandated by POSIX http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_03_01 ). The result on Solaris 10 is: currency = || positive sign = || negative sign = || strfmon result for positive value = | 123| strfmon result for negative value = |- 123| strfmon result with 2 fractional digits: = |123.50| This is not POSIX compliant, 1. because of the '-' sign, 2. because it produces a different number of characters in the negative and in the positive case, which is against what POSIX says for the '#' flag (lines 65387 to 65389): To ensure alignment, any characters appearing before or after the number in the formatted output such as currency or sign symbols are padded as necessary with <space> characters to make their positive and negative formats an equal length. The result on macOS 10.13 is: currency = || positive sign = || negative sign = || strfmon result for positive value = | 123 | strfmon result for negative value = |( 123)| strfmon result with 2 fractional digits: = |123.50| This is not POSIX compliant, because the test program does not specify the '+' nor '(' flag, and POSIX says (lines 65363 to 65366): If '+' is specified, the locale's equivalent of '+' and '-' are used (for example, in many locales, the empty string if positive and '-' if negative). If '(' is specified, negative amounts are enclosed within parentheses. If neither flag is specified, the '+' style is used. In summary, out of four implementations, only one is POSIX compliant, and it produces highly misleading / dangerous results. Desired Action: Remove strfmon and strfmon_l from the standard. Also remove <monetary.h> from the standard, since its only purpose is the declare these functions. Or otherwise, change the standard so that the glibc results become the only compliant results. ====================================================================== Issue History Date Modified Username Field Change ====================================================================== 2018-08-12 19:23 bhaible New Issue 2018-08-12 19:23 bhaible Name => Bruno Haible 2018-08-12 19:23 bhaible Organization => GNU 2018-08-12 19:23 bhaible Section => strfmon 2018-08-12 19:23 bhaible Page Number => 2039 to 2043 2018-08-12 19:23 bhaible Line Number => 65327 to 65492 ======================================================================