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  
======================================================================


Reply via email to