bug-gnulib
[Top][All Lists]
Advanced

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

MSVC and fpending


From: Bruno Haible
Subject: MSVC and fpending
Date: Tue, 13 Dec 2016 02:58:29 +0100
User-agent: KMail/4.8.5 (Linux/3.8.0-44-generic; KDE/4.8.5; x86_64; ; )

Hi Jim,

On Windows with MSVC, the 'fpending' module does not pass its test,
because config.h defines

  #define PENDING_OUTPUT_N_BYTES 1

In order to get this right, the expression should be

  ((struct { unsigned char *_ptr; unsigned char *_base; } *) fp)->_ptr - 
((struct { unsigned char *_ptr; unsigned char *_base; } *) fp)->_base

But this is code duplication (with stdio-impl.h) and produces compiler warnings
("warning C4116: unnamed type definition in parentheses").

I would therefore propose to convert the 'fpending' module to the same
form as the other stdioext modules, with code that uses stdio-impl.h.
Yes, this replaces some autoconfiguration by #ifs. But porting to future
platforms is not that frequent, because hardly anyone creates freshly new stdio
implementations nowadays, and not that hard, because fseeko.c gives some hints.

Here's the proposed patch. It drops the 'old glibc iostream' case, which
I haven't encountered in 8 years. But it works on MSVC.


2016-12-12  Bruno Haible  <address@hidden>

        fpending: Port to native Windows with MSVC.
        * lib/fpending.c: Include stdio-impl.h.
        (__fpending): Include all known implementations. Err out if it's not
        ported.
        * m4/fpending.m4 (gl_PREREQ_FPENDING): Remove macro.
        * modules/fpending (Files): Add lib/stdio-impl.h.
        (configure.ac): Don't invoke gl_PREREQ_FPENDING.

diff --git a/lib/fpending.c b/lib/fpending.c
index a503b9f..14ef222 100644
--- a/lib/fpending.c
+++ b/lib/fpending.c
@@ -19,12 +19,42 @@
 
 #include <config.h>
 
+/* Specification.  */
 #include "fpending.h"
 
+#include "stdio-impl.h"
+
 /* Return the number of pending (aka buffered, unflushed)
    bytes on the stream, FP, that is open for writing.  */
 size_t
 __fpending (FILE *fp)
 {
-  return PENDING_OUTPUT_N_BYTES;
+  /* Most systems provide FILE as a struct and the necessary bitmask in
+     <stdio.h>, because they need it for implementing getc() and putc() as
+     fast macros.  */
+#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, 
Linux libc5 */
+  return fp->_IO_write_ptr - fp->_IO_write_base;
+#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
+  /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Android */
+  return fp->_p - fp->_bf._base;
+#elif defined __EMX__                /* emx+gcc */
+  return fp->_ptr - fp->_buffer;
+#elif defined __minix                /* Minix */
+  return fp_->_ptr - fp_->_buf;
+#elif defined _IOERR                 /* AIX, HP-UX, IRIX, OSF/1, Solaris, 
OpenServer, mingw, MSVC, NonStop Kernel */
+  return (fp_->_ptr ? fp_->_ptr - fp_->_base : 0);
+#elif defined __UCLIBC__             /* uClibc */
+  return (fp->__modeflags & __FLAG_WRITING ? fp->__bufpos - fp->__bufstart : 
0);
+#elif defined __QNX__                /* QNX */
+  return (fp->_Mode & 0x2000 /*_MWRITE*/ ? fp->_Next - fp->_Buf : 0);
+#elif defined __MINT__               /* Atari FreeMiNT */
+  return fp->__bufp - fp->__buffer;
+#elif defined EPLAN9                 /* Plan9 */
+  return fp->wp - fp->buf;
+#elif defined __VMS                  /* VMS */
+  return (*fp)->_ptr - (*fp)->_base;
+#else
+# error "Please port gnulib fpending.c to your platform!"
+  return 1;
+#endif
 }
diff --git a/m4/fpending.m4 b/m4/fpending.m4
index a446156..f6776a8 100644
--- a/m4/fpending.m4
+++ b/m4/fpending.m4
@@ -1,4 +1,4 @@
-# serial 21
+# serial 22
 
 # Copyright (C) 2000-2001, 2004-2016 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -11,7 +11,7 @@ dnl and Ulrich Drepper.
 
 dnl Find out how to determine the number of pending output bytes on a stream.
 dnl glibc (2.1.93 and newer) and Solaris provide __fpending.  On other systems,
-dnl we have to grub around in the FILE struct.
+dnl we have to grub around in the (possibly opaque) FILE struct.
 
 AC_DEFUN([gl_FUNC_FPENDING],
 [
@@ -34,66 +34,3 @@ AC_DEFUN([gl_FUNC_FPENDING],
     AC_CHECK_DECLS([__fpending], [], [], [$fp_headers])
   fi
 ])
-
-AC_DEFUN([gl_PREREQ_FPENDING],
-[
-  AC_CACHE_CHECK(
-              [how to determine the number of pending output bytes on a 
stream],
-                 ac_cv_sys_pending_output_n_bytes,
-    [
-      for ac_expr in                                                    \
-                                                                        \
-          '# glibc2'                                                    \
-          'fp->_IO_write_ptr - fp->_IO_write_base'                      \
-                                                                        \
-          '# traditional Unix'                                          \
-          'fp->_ptr - fp->_base'                                        \
-                                                                        \
-          '# BSD'                                                       \
-          'fp->_p - fp->_bf._base'                                      \
-                                                                        \
-          '# SCO, Unixware'                                             \
-          '(fp->__ptr ? fp->__ptr - fp->__base : 0)'                    \
-                                                                        \
-          '# QNX'                                                       \
-          '(fp->_Mode & 0x2000 /*_MWRITE*/ ? fp->_Next - fp->_Buf : 0)' \
-                                                                        \
-          '# old glibc?'                                                \
-          'fp->__bufp - fp->__buffer'                                   \
-                                                                        \
-          '# old glibc iostream?'                                       \
-          'fp->_pptr - fp->_pbase'                                      \
-                                                                        \
-          '# emx+gcc'                                                   \
-          'fp->_ptr - fp->_buffer'                                      \
-                                                                        \
-          '# Minix'                                                     \
-          'fp->_ptr - fp->_buf'                                         \
-                                                                        \
-          '# Plan9'                                                     \
-          'fp->wp - fp->buf'                                            \
-                                                                        \
-          '# VMS'                                                       \
-          '(*fp)->_ptr - (*fp)->_base'                                  \
-                                                                        \
-          '# e.g., DGUX R4.11; the info is not available'               \
-          1                                                             \
-          ; do
-
-        # Skip each embedded comment.
-        case "$ac_expr" in '#'*) continue;; esac
-
-        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]],
-          [[FILE *fp = stdin; (void) ($ac_expr);]])],
-          [fp_done=yes]
-        )
-        test "$fp_done" = yes && break
-      done
-
-      ac_cv_sys_pending_output_n_bytes=$ac_expr
-    ]
-  )
-  AC_DEFINE_UNQUOTED([PENDING_OUTPUT_N_BYTES],
-    $ac_cv_sys_pending_output_n_bytes,
-    [the number of pending output bytes on stream 'fp'])
-])
diff --git a/modules/fpending b/modules/fpending
index 1375eb1..8dc4bee 100644
--- a/modules/fpending
+++ b/modules/fpending
@@ -4,6 +4,7 @@ Determine the number of bytes waiting in the output buffer of a 
stream.
 Files:
 lib/fpending.h
 lib/fpending.c
+lib/stdio-impl.h
 m4/fpending.m4
 
 Depends-on:
@@ -12,7 +13,6 @@ configure.ac:
 gl_FUNC_FPENDING
 if test $gl_cv_func___fpending = no; then
   AC_LIBOBJ([fpending])
-  gl_PREREQ_FPENDING
 fi
 
 Makefile.am:




reply via email to

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