Blame wcsmbs/tst-fgetwc-after-eof.c

Packit 6c4009
/* Bug 1190: EOF conditions are supposed to be sticky.
Packit 6c4009
   Copyright (C) 2018 Free Software Foundation.
Packit 6c4009
   Copying and distribution of this file, with or without modification,
Packit 6c4009
   are permitted in any medium without royalty provided the copyright
Packit 6c4009
   notice and this notice are preserved. This file is offered as-is,
Packit 6c4009
   without any warranty.  */
Packit 6c4009
Packit 6c4009
/* ISO C1999 specification of fgetwc:
Packit 6c4009
Packit 6c4009
       #include <stdio.h>
Packit 6c4009
       #include <wchar.h>
Packit 6c4009
       wint_t fgetwc (FILE *stream);
Packit 6c4009
Packit 6c4009
   Description
Packit 6c4009
Packit 6c4009
     If the end-of-file indicator for the input stream pointed to by
Packit 6c4009
     stream is not set and a next wide character is present, the
Packit 6c4009
     fgetwc function obtains that wide character as a wchar_t
Packit 6c4009
     converted to a wint_t and advances the associated file position
Packit 6c4009
     indicator for the stream (if defined).
Packit 6c4009
Packit 6c4009
  Returns
Packit 6c4009
Packit 6c4009
     If the end-of-file indicator for the stream is set, or if the
Packit 6c4009
     stream is at end-of-file, the end- of-file indicator for the
Packit 6c4009
     stream is set and the fgetwc function returns WEOF. Otherwise,
Packit 6c4009
     the fgetwc function returns the next wide character from the
Packit 6c4009
     input stream pointed to by stream. If a read error occurs, the
Packit 6c4009
     error indicator for the stream is set and the fgetwc function
Packit 6c4009
     returns WEOF. If an encoding error occurs (including too few
Packit 6c4009
     bytes), the value of the macro EILSEQ is stored in errno and the
Packit 6c4009
     fgetwc function returns WEOF.
Packit 6c4009
Packit 6c4009
   The requirement to return WEOF "if the end-of-file indicator for the
Packit 6c4009
   stream is set" was new in C99; the language in the 1995 edition of
Packit 6c4009
   the standard was ambiguous.  Historically, BSD-derived Unix always
Packit 6c4009
   had the C99 behavior, whereas in System V fgetwc would attempt to
Packit 6c4009
   call read() again before returning EOF again.  Prior to version 2.28,
Packit 6c4009
   glibc followed the System V behavior even though this does not
Packit 6c4009
   comply with C99.
Packit 6c4009
Packit 6c4009
   See
Packit 6c4009
   <https://sourceware.org/bugzilla/show_bug.cgi?id=1190>,
Packit 6c4009
   <https://sourceware.org/bugzilla/show_bug.cgi?id=19476>,
Packit 6c4009
   and the thread at
Packit 6c4009
   <https://sourceware.org/ml/libc-alpha/2012-09/msg00343.html>
Packit 6c4009
   for more detail.  */
Packit 6c4009
Packit 6c4009
#include <support/tty.h>
Packit 6c4009
#include <support/check.h>
Packit 6c4009
Packit 6c4009
#include <fcntl.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <wchar.h>
Packit 6c4009
Packit 6c4009
#define XWRITE(fd, s, msg) do {                         \
Packit 6c4009
    if (write (fd, s, sizeof s - 1) != sizeof s - 1)    \
Packit 6c4009
      {                                                 \
Packit 6c4009
        perror ("write " msg);                          \
Packit 6c4009
        return 1;                                       \
Packit 6c4009
      }                                                 \
Packit 6c4009
  } while (0)
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
do_test (void)
Packit 6c4009
{
Packit 6c4009
  /* The easiest way to set up the conditions under which you can
Packit 6c4009
     notice whether the end-of-file indicator is sticky, is with a
Packit 6c4009
     pseudo-tty.  This is also the case which applications are most
Packit 6c4009
     likely to care about.  And it avoids any question of whether and
Packit 6c4009
     how it is legitimate to access the same physical file with two
Packit 6c4009
     independent FILE objects.  */
Packit 6c4009
  int outer_fd, inner_fd;
Packit 6c4009
  FILE *fp;
Packit 6c4009
Packit 6c4009
  support_openpty (&outer_fd, &inner_fd, 0, 0, 0);
Packit 6c4009
  fp = fdopen (inner_fd, "r+");
Packit 6c4009
  if (!fp)
Packit 6c4009
    {
Packit 6c4009
      perror ("fdopen");
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  XWRITE (outer_fd, "abc\n\004", "first line + EOF");
Packit 6c4009
  TEST_COMPARE (fgetwc (fp), L'a');
Packit 6c4009
  TEST_COMPARE (fgetwc (fp), L'b');
Packit 6c4009
  TEST_COMPARE (fgetwc (fp), L'c');
Packit 6c4009
  TEST_COMPARE (fgetwc (fp), L'\n');
Packit 6c4009
  TEST_COMPARE (fgetwc (fp), WEOF);
Packit 6c4009
Packit 6c4009
  TEST_VERIFY_EXIT (feof (fp));
Packit 6c4009
  TEST_VERIFY_EXIT (!ferror (fp));
Packit 6c4009
Packit 6c4009
  XWRITE (outer_fd, "d\n", "second line");
Packit 6c4009
Packit 6c4009
  /* At this point, there is a new full line of input waiting in the
Packit 6c4009
     kernelside input buffer, but we should still observe EOF from
Packit 6c4009
     stdio, because the end-of-file indicator has not been cleared.  */
Packit 6c4009
  TEST_COMPARE (fgetwc (fp), WEOF);
Packit 6c4009
Packit 6c4009
  /* Clearing EOF should reveal the next line of input.  */
Packit 6c4009
  clearerr (fp);
Packit 6c4009
  TEST_COMPARE (fgetwc (fp), L'd');
Packit 6c4009
  TEST_COMPARE (fgetwc (fp), L'\n');
Packit 6c4009
Packit 6c4009
  fclose (fp);
Packit 6c4009
  close (outer_fd);
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#include <support/test-driver.c>