tst-fgetwc-after-eof.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /* Bug 1190: EOF conditions are supposed to be sticky.
  2. Copyright (C) 2018 Free Software Foundation.
  3. Copying and distribution of this file, with or without modification,
  4. are permitted in any medium without royalty provided the copyright
  5. notice and this notice are preserved. This file is offered as-is,
  6. without any warranty. */
  7. /* ISO C1999 specification of fgetwc:
  8. #include <stdio.h>
  9. #include <wchar.h>
  10. wint_t fgetwc (FILE *stream);
  11. Description
  12. If the end-of-file indicator for the input stream pointed to by
  13. stream is not set and a next wide character is present, the
  14. fgetwc function obtains that wide character as a wchar_t
  15. converted to a wint_t and advances the associated file position
  16. indicator for the stream (if defined).
  17. Returns
  18. If the end-of-file indicator for the stream is set, or if the
  19. stream is at end-of-file, the end- of-file indicator for the
  20. stream is set and the fgetwc function returns WEOF. Otherwise,
  21. the fgetwc function returns the next wide character from the
  22. input stream pointed to by stream. If a read error occurs, the
  23. error indicator for the stream is set and the fgetwc function
  24. returns WEOF. If an encoding error occurs (including too few
  25. bytes), the value of the macro EILSEQ is stored in errno and the
  26. fgetwc function returns WEOF.
  27. The requirement to return WEOF "if the end-of-file indicator for the
  28. stream is set" was new in C99; the language in the 1995 edition of
  29. the standard was ambiguous. Historically, BSD-derived Unix always
  30. had the C99 behavior, whereas in System V fgetwc would attempt to
  31. call read() again before returning EOF again. Prior to version 2.28,
  32. glibc followed the System V behavior even though this does not
  33. comply with C99.
  34. See
  35. <https://sourceware.org/bugzilla/show_bug.cgi?id=1190>,
  36. <https://sourceware.org/bugzilla/show_bug.cgi?id=19476>,
  37. and the thread at
  38. <https://sourceware.org/ml/libc-alpha/2012-09/msg00343.html>
  39. for more detail. */
  40. #include <support/tty.h>
  41. #include <support/check.h>
  42. #include <fcntl.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <unistd.h>
  47. #include <wchar.h>
  48. #define XWRITE(fd, s, msg) do { \
  49. if (write (fd, s, sizeof s - 1) != sizeof s - 1) \
  50. { \
  51. perror ("write " msg); \
  52. return 1; \
  53. } \
  54. } while (0)
  55. int
  56. do_test (void)
  57. {
  58. /* The easiest way to set up the conditions under which you can
  59. notice whether the end-of-file indicator is sticky, is with a
  60. pseudo-tty. This is also the case which applications are most
  61. likely to care about. And it avoids any question of whether and
  62. how it is legitimate to access the same physical file with two
  63. independent FILE objects. */
  64. int outer_fd, inner_fd;
  65. FILE *fp;
  66. support_openpty (&outer_fd, &inner_fd, 0, 0, 0);
  67. fp = fdopen (inner_fd, "r+");
  68. if (!fp)
  69. {
  70. perror ("fdopen");
  71. return 1;
  72. }
  73. XWRITE (outer_fd, "abc\n\004", "first line + EOF");
  74. TEST_COMPARE (fgetwc (fp), L'a');
  75. TEST_COMPARE (fgetwc (fp), L'b');
  76. TEST_COMPARE (fgetwc (fp), L'c');
  77. TEST_COMPARE (fgetwc (fp), L'\n');
  78. TEST_COMPARE (fgetwc (fp), WEOF);
  79. TEST_VERIFY_EXIT (feof (fp));
  80. TEST_VERIFY_EXIT (!ferror (fp));
  81. XWRITE (outer_fd, "d\n", "second line");
  82. /* At this point, there is a new full line of input waiting in the
  83. kernelside input buffer, but we should still observe EOF from
  84. stdio, because the end-of-file indicator has not been cleared. */
  85. TEST_COMPARE (fgetwc (fp), WEOF);
  86. /* Clearing EOF should reveal the next line of input. */
  87. clearerr (fp);
  88. TEST_COMPARE (fgetwc (fp), L'd');
  89. TEST_COMPARE (fgetwc (fp), L'\n');
  90. fclose (fp);
  91. close (outer_fd);
  92. return 0;
  93. }
  94. #include <support/test-driver.c>