This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]