bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Austin group ruling on ungetc vs. fflush


From: Bruno Haible
Subject: Re: Austin group ruling on ungetc vs. fflush
Date: Fri, 16 Jan 2009 00:24:28 +0100
User-agent: KMail/1.9.9

The fflush-after-ungetc test fails on glibc, *BSD, mingw platforms.
This makes it work for glibc systems - at the cost of introducing a
slim override of fflush().

Eric, comments or objections?


2009-01-15  Bruno Haible  <address@hidden>

        Make fflush-after-ungetc POSIX compliant on glibc systems.
        * m4/fflush.m4 (gl_FUNC_FFLUSH): Test also the behaviour of fflush
        after ungetc.
        * lib/fflush.c (clear_ungetc_buffer): Implement for glibc systems.
        (rpl_fflush): On glibc systems, simply call the system's fflush
        function after clearing the ungetc buffer.
        * lib/fseeko.c (rpl_fseeko): Don't try to lseek past the end of file.
        Instead, lseek only to the end of file, then use the system's fseeko
        for the rest. On glibc systems, reset the EOF indicator bit.

--- m4/fflush.m4.orig   2009-01-16 00:20:08.000000000 +0100
+++ m4/fflush.m4        2009-01-16 00:04:17.000000000 +0100
@@ -1,6 +1,6 @@
-# fflush.m4 serial 6
+# fflush.m4 serial 7
 
-# Copyright (C) 2007-2008 Free Software Foundation, Inc.
+# Copyright (C) 2007-2009 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -22,6 +22,7 @@
        ]], [[FILE *f = fopen ("conftest.txt", "r");
         char buffer[10];
         int fd;
+        int c;
         if (f == NULL)
           return 1;
         fd = fileno (f);
@@ -30,17 +31,31 @@
         /* For deterministic results, ensure f read a bigger buffer.  */
         if (lseek (fd, 0, SEEK_CUR) == 5)
           return 3;
-        /* POSIX requires fflush-fseek to set file offset of fd.  */
+        /* POSIX requires fflush-fseek to set file offset of fd.  This fails
+           on BSD systems and on mingw.  */
         if (fflush (f) != 0 || fseek (f, 0, SEEK_CUR) != 0)
           return 4;
         if (lseek (fd, 0, SEEK_CUR) != 5)
           return 5;
-        /* TODO: Verify behaviour of fflush after ungetc, see
-           
<http://lists.gnu.org/archive/html/bug-gnulib/2008-03/msg00131.html>.  */
+        /* Verify behaviour of fflush after ungetc. See
+           <http://www.opengroup.org/austin/aardvark/latest/xshbug3.txt>  */
+        /* Verify behaviour of fflush after a backup ungetc.  This fails on
+           mingw.  */
+        c = fgetc (f);
+        ungetc (c, f);
+        fflush (f);
+        if (fgetc (f) != c)
+          return 6;
+        /* Verify behaviour of fflush after a non-backup ungetc.  This fails
+           on glibc 2.8 and on BSD systems.  */
+        c = fgetc (f);
+        ungetc ('@', f);
+        fflush (f);
+        if (fgetc (f) != c)
+          return 7;
         return 0;
        ]])], [gl_cv_func_fflush_stdin=yes], [gl_cv_func_fflush_stdin=no],
-     [dnl Pessimistically assume fflush is broken.  This is wrong for
-      dnl at least glibc and cygwin; but lib/fflush.c takes this into account.
+     [dnl Pessimistically assume fflush is broken.
       gl_cv_func_fflush_stdin=no])
      rm conftest.txt
     ])
--- lib/fflush.c.orig   2009-01-16 00:20:08.000000000 +0100
+++ lib/fflush.c        2009-01-15 23:51:54.000000000 +0100
@@ -1,5 +1,5 @@
 /* fflush.c -- allow flushing input streams
-   Copyright (C) 2007-2008 Free Software Foundation, Inc.
+   Copyright (C) 2007-2009 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -34,7 +34,11 @@
 static inline void
 clear_ungetc_buffer (FILE *fp)
 {
-#if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, 
DragonFly, MacOS X, Cygwin */
+#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, 
Linux libc5 */
+  if (fp->_flags & _IO_IN_BACKUP)
+    /* _IO_free_backup_area is a bit complicated.  Simply call fseek.  */
+    fseek (fp, 0, SEEK_CUR);
+#elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, 
DragonFly, MacOS X, Cygwin */
   if (HASUB (fp))
     {
       fp_->_p += fp_->_r;
@@ -123,6 +127,12 @@
      pushed-back bytes and the read-ahead bytes.  */
   clear_ungetc_buffer (stream);
 
+#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, 
Linux libc5 */
+
+  return fflush (stream);
+
+#else
+
   /* POSIX does not specify fflush behavior for non-seekable input
      streams.  Some implementations purge unread data, some return
      EBADF, some do nothing.  */
@@ -140,7 +150,7 @@
   if (result != 0)
     return result;
 
-#if (defined __sferror || defined __DragonFly__) && defined __SNPT /* FreeBSD, 
NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
+# if (defined __sferror || defined __DragonFly__) && defined __SNPT /* 
FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
 
   {
     /* Disable seek optimization for the next fseeko call.  This tells the
@@ -154,7 +164,7 @@
   }
   return result;
 
-#else
+# else
 
   pos = lseek (fileno (stream), pos, SEEK_SET);
   if (pos == -1)
@@ -165,5 +175,6 @@
 
   return 0;
 
+# endif
 #endif
 }
--- lib/fseeko.c.orig   2009-01-16 00:20:08.000000000 +0100
+++ lib/fseeko.c        2009-01-16 00:18:29.000000000 +0100
@@ -1,5 +1,5 @@
 /* An fseeko() function that, together with fflush(), is POSIX compliant.
-   Copyright (C) 2007-2008 Free Software Foundation, Inc.
+   Copyright (C) 2007-2009 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -86,7 +86,14 @@
   #error "Please port gnulib fseeko.c to your platform! Look at the code in 
fpurge.c, then report this to bug-gnulib."
 #endif
     {
-      off_t pos = lseek (fileno (fp), offset, whence);
+      /* We get here when an fflush() call immediately preceded this one.  We
+        know there are no buffers.
+        POSIX requires us to modify the file descriptor's position.
+        But we cannot position beyond end of file here.  */
+      off_t pos =
+       lseek (fileno (fp),
+              whence == SEEK_END && offset > 0 ? 0 : offset,
+              whence);
       if (pos == -1)
        {
 #if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, 
DragonFly, MacOS X, Cygwin */
@@ -94,20 +101,22 @@
 #endif
          return -1;
        }
-      else
-       {
-#if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, 
DragonFly, MacOS X, Cygwin */
-         fp_->_offset = pos;
-         fp_->_flags |= __SOFF;
-         fp_->_flags &= ~__SEOF;
+
+#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, 
Linux libc5 */
+      fp->_flags &= ~_IO_EOF_SEEN;
+#elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, 
DragonFly, MacOS X, Cygwin */
+      fp_->_offset = pos;
+      fp_->_flags |= __SOFF;
+      fp_->_flags &= ~__SEOF;
 #elif defined __EMX__               /* emx+gcc */
-          fp->_flags &= ~_IOEOF;
+      fp->_flags &= ~_IOEOF;
 #elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, 
OpenServer, mingw */
-          fp->_flag &= ~_IOEOF;
+      fp->_flag &= ~_IOEOF;
 #endif
-         return 0;
-       }
+      /* If we were not requested to position beyond end of file, we're
+        done.  */
+      if (!(whence == SEEK_END && offset > 0))
+       return 0;
     }
-  else
-    return fseeko (fp, offset, whence);
+  return fseeko (fp, offset, whence);
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]