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 <br...@clisp.org> 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: