Re: perror() changes the orientation of stderr to byte-oriented mode if stderr is not oriented yet.

Craig Howland <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
On 06/27/2018 08:55 AM, Corinna Vinschen wrote:
> ...
>
>
> On Jun 27 20:01, Takashi Yano wrote:
>> POSIX states:
>> The perror() function shall not change the orientation of the standard
>> error stream.
>>
>> However, cygwin perror() function changes the orientation of stderr to
>> byte-oriented mode if stderr is not oriented yet.
I suggest that POSIX is in error.  The POSIX statement about not changing the 
orientation is an extension to the C standard (CX, to be precise).  POSIX is 
always careful to defer to the C standard, which I think does indirectly specify 
that perror() is byte-oriented.  The C standard actually does not directly talk 
about the orientation of perror().  However, it directly defines (quoting from 
the N1570 C11 draft):

"The input/output functions are given the following collective terms:
— The wide character input functions — those functions described in 7.29 that 
perform input into wide characters and wide strings: fgetwc, fgetws, getwc, 
getwchar, fwscanf, wscanf, vfwscanf, and vwscanf.
— The wide character output functions — those functions described in 7.29 that 
perform output from wide characters and wide strings: fputwc, fputws, putwc, 
putwchar, fwprintf, wprintf, vfwprintf, and vwprintf.
— The wide character input/output functions — the union of the ungetwc function, 
the wide character input functions, and the wide character output functions.
— The byte input/output functions — those functions described in this subclause 
that perform input/output: fgetc, fgets, fprintf, fputc, fputs, fread, fscanf, 
fwrite, getc, getchar, printf, putc, putchar, puts, scanf, ungetc, vfprintf, 
vfscanf, vprintf, and vscanf."

Please note that perror() is not listed.  While this could be interpreted to 
mean it can be both, the proper way for that have to been done would be for it 
to appear in both lists--which it does not.  However, perror() is defined in the 
same stdio.h subclause (i.e. 7.21) as all of the byte functions, against the 
wide-character functions in wchar.h (7.29).  So even though the C standard is 
sloppy and does not directly have perror() in the enumerated list, it is 
included by the general statement about the subclause. However, you could argue 
that it was purposely left out, which is why they bothered to list the others.  
Against this are the definition or perror(), itself, and that they really should 
have listed perror() as an exception if it was so intended, and (as 
already-mentioned) perror() should be in both lists if it is to be dual-oriented.

Here is the argument based on the perror() definition:

"void perror(const char *s);
...
It writes a sequence of characters to the standard error stream thus: first (if s 
is not a null pointer and the character pointed to by s is not the null 
character), the string pointed to by s followed by a colon (:) and a space; then 
an appropriate error message string followed by a new-line character."

Things to note:
1)  It is a regular character pointer, not a wide character pointer.  Those 
characters, if supplied, are written.  (It says nothing about converting them to 
wide if need be, it says "the string pointed to by s".)
2)  "error message string".  It does not say 'or wide-character error message 
string if needed'.
3)  Followed by a "new-line character".  It does not say "new-line wide 
character", which is used throughout the wchar.h section (7.29).

So there is definitely a weakness in the C standard, but I think it is clear 
that perror() is a byte output function.  If the user wants to print to a 
wide-character stream, the only pure way to do it would be to turn strerror() 
(used by perror()) output into a wide-character string.  POSIX noted this 
weakness, but fixed it with a bad extension, rather than classifying perror() as 
byte--which is clearly is.

Therefore, the newlib perror() behavior is correct and should not be changed.  
It definitely is a mess and there really ought to be a perrorw() function.

(Granted, I should probably submit these arguments to POSIX for evaluation, but 
I don't know how.  Perhaps Eric Blake might be able to help with this, 
potentially with an off-list discussion.)

Craig
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.