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

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