This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: perror() changes the orientation of stderr to byte-oriented mode if stderr is not oriented yet.
- From: Craig Howland <howland at LGSInnovations dot com>
- To: <newlib at sourceware dot org>
- Date: Thu, 28 Jun 2018 12:28:10 -0400
- Subject: Re: perror() changes the orientation of stderr to byte-oriented mode if stderr is not oriented yet.
- References: <20180627200116.ddd80f78597f8fd3f09d5d4b@nifty.ne.jp> <20180627125503.GV28757@calimero.vinschen.de>
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