This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: stdio_ext.h function implementations
- From: Yaakov Selkowitz <yselkowi at redhat dot com>
- To: newlib at sourceware dot org
- Date: Wed, 10 Dec 2014 23:36:53 -0600
- Subject: Re: stdio_ext.h function implementations
- Authentication-results: sourceware.org; auth=none
- References: <5487625C dot 1070208 at redhat dot com> <20141210094045 dot GA24329 at calimero dot vinschen dot de>
On 2014-12-10 03:40, Corinna Vinschen wrote:
On Dec 9 14:58, Yaakov Selkowitz wrote:
Currently, the bulk of the <stdio_ext.h> functions[1][2] are implemented as
inline code, or macros on non-gcc-compatible toolchains. However, there are
a few issues with that:
* Header-only implementations result in false negatives from AC_CHECK_FUNC
tests and the like. For instance, cpio FTBFS on Cygwin currently because it
tries to implement a replacement for a "missing" __fpending which conflicts
with the one already in <stdio_ext.h>.
* Macro implementations of libc functions need to be undef'ed and backed by
real functions with C++ (otherwise you get syntax errors in the ::func
form). Are the inline implementations used by GCC safe for these purposes?
Apart from the fact that the header was broken (too many "inline", fixed
now), inline functions are safe. ::__fpending(stdin) is a valid expression.
* No documentation is generated for these functions.
Patch attached; it also fixes the spelling of __fwritable() to match
Solaris and glibc.
Note that this code will only be pulled in by (1) AC_CHECK_FUNC
configure tests or the like, (2) a non-__GNUC__-defining C++ compiler
(IOW *not* g++, clang++, or icpc, nor *any* _C_ compiler), or (3)
dlopen()ing these functions from a shared libc (e.g. Cygwin). In all
other cases, the inlines/macros in <stdio_ext.h> will be used.
Therefore, I see little loss in providing a single .c file for these.
These are #ifndef __rtems__ because they have chosen not to support
<stdio_ext.h> at all.
The functions call _newlib_flockfile_{start,end} even though the macros
do not, to match the behaviour of clearerr() and feof().
--
Yaakov Selkowitz
Associate Software Engineer, ARM
Red Hat, Inc.
2014-12-10 Yaakov Selkowitz <yselkowi@...>
* libc/include/stdio_ext.h: Rename __fwriteable to __fwritable,
leaving a macro for compatibility.
[!__GNUC__]: Declare real functions for the macros, and make
the macros conditional on !__cplusplus.
* libc/stdio/Makefile.am: Add new stdio_ext.c file.
* libc/stdio/Makefile.in: Regenerate.
* libc/stdio/stdio.tex: Include stdio_ext.def.
* libc/stdio/stdio_ext.c: New file.
Index: libc/include/stdio_ext.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/stdio_ext.h,v
retrieving revision 1.3
diff -u -p -r1.3 stdio_ext.h
--- libc/include/stdio_ext.h 10 Dec 2014 09:39:06 -0000 1.3
+++ libc/include/stdio_ext.h 11 Dec 2014 04:33:51 -0000
@@ -23,6 +23,9 @@ void _EXFUN(__fpurge,(FILE *));
int __fsetlocking (FILE *__fp, int __type);
*/
+/* this function was previously misspelled */
+#define __fwriteable(__fp) __fwritable(__fp)
+
#ifdef __GNUC__
_ELIDABLE_INLINE size_t
@@ -38,7 +41,7 @@ _ELIDABLE_INLINE int
__freadable (FILE *__fp) { return (__fp->_flags & (__SRD | __SRW)) != 0; }
_ELIDABLE_INLINE int
-__fwriteable (FILE *__fp) { return (__fp->_flags & (__SWR | __SRW)) != 0; }
+__fwritable (FILE *__fp) { return (__fp->_flags & (__SWR | __SRW)) != 0; }
_ELIDABLE_INLINE int
__flbf (FILE *__fp) { return (__fp->_flags & __SLBF) != 0; }
@@ -48,14 +51,26 @@ __fpending (FILE *__fp) { return __fp->_
#else
+size_t _EXFUN(__fbufsize,(FILE *));
+int _EXFUN(__freading,(FILE *));
+int _EXFUN(__fwriting,(FILE *));
+int _EXFUN(__freadable,(FILE *));
+int _EXFUN(__fwritable,(FILE *));
+int _EXFUN(__flbf,(FILE *));
+size_t _EXFUN(__fpending,(FILE *));
+
+#ifndef __cplusplus
+
#define __fbufsize(__fp) ((size_t) (__fp)->_bf._size)
#define __freading(__fp) (((__fp)->_flags & __SRD) != 0)
#define __fwriting(__fp) (((__fp)->_flags & __SWR) != 0)
#define __freadable(__fp) (((__fp)->_flags & (__SRD | __SRW)) != 0)
-#define __fwriteable(__fp) (((__fp)->_flags & (__SWR | __SRW)) != 0)
+#define __fwritable(__fp) (((__fp)->_flags & (__SWR | __SRW)) != 0)
#define __flbf(__fp) (((__fp)->_flags & __SLBF) != 0)
#define __fpending(__fp) ((size_t) ((__fp)->_p - (__fp)->_bf._base))
+#endif /* __cplusplus */
+
#endif /* __GNUC__ */
_END_STD_C
Index: libc/stdio/Makefile.am
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/Makefile.am,v
retrieving revision 1.35
diff -u -p -r1.35 Makefile.am
--- libc/stdio/Makefile.am 4 Jul 2014 17:21:42 -0000 1.35
+++ libc/stdio/Makefile.am 11 Dec 2014 04:33:52 -0000
@@ -155,6 +155,7 @@ ELIX_4_SOURCES = \
open_memstream.c \
putwc.c \
putwchar.c \
+ stdio_ext.c \
swprintf.c \
swscanf.c \
ungetwc.c \
@@ -391,6 +392,7 @@ CHEWOUT_FILES = \
setvbuf.def \
sprintf.def \
sscanf.def \
+ stdio_ext.def \
swprintf.def \
swscanf.def \
tmpfile.def \
@@ -457,6 +459,7 @@ $(lpfx)sniprintf.$(oext): local.h
$(lpfx)sprintf.$(oext): local.h
$(lpfx)sscanf.$(oext): local.h
$(lpfx)stdio.$(oext): local.h
+$(lpfx)stdio_ext.$(oext): local.h
if NEWLIB_NANO_FORMATTED_IO
$(lpfx)nano-svfprintf.$(oext): local.h nano-vfprintf_local.h
$(lpfx)nano-svfscanf.$(oext): local.h nano-vfscanf_local.h
Index: libc/stdio/Makefile.in
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/Makefile.in,v
retrieving revision 1.56
diff -u -p -r1.56 Makefile.in
--- libc/stdio/Makefile.in 4 Jul 2014 17:21:42 -0000 1.56
+++ libc/stdio/Makefile.in 11 Dec 2014 04:33:53 -0000
@@ -152,6 +152,7 @@ am__objects_2 = $(am__objects_1) lib_a-c
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ lib_a-open_memstream.$(OBJEXT) \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ lib_a-putwc.$(OBJEXT) \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ lib_a-putwchar.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ lib_a-stdio_ext.$(OBJEXT) \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ lib_a-swprintf.$(OBJEXT) \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ lib_a-swscanf.$(OBJEXT) \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ lib_a-ungetwc.$(OBJEXT) \
@@ -214,6 +215,7 @@ am__objects_8 = $(am__objects_7) clearer
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ open_memstream.lo \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ putwc.lo \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ putwchar.lo \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ stdio_ext.lo \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ swprintf.lo \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ swscanf.lo \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ ungetwc.lo \
@@ -521,6 +523,7 @@ GENERAL_SOURCES = \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ open_memstream.c \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ putwc.c \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ putwchar.c \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ stdio_ext.c \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ swprintf.c \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ swscanf.c \
@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ ungetwc.c \
@@ -663,6 +666,7 @@ CHEWOUT_FILES = \
setvbuf.def \
sprintf.def \
sscanf.def \
+ stdio_ext.def \
swprintf.def \
swscanf.def \
tmpfile.def \
@@ -1405,6 +1409,12 @@ lib_a-putwchar.o: putwchar.c
lib_a-putwchar.obj: putwchar.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-putwchar.obj `if test -f 'putwchar.c'; then $(CYGPATH_W) 'putwchar.c'; else $(CYGPATH_W) '$(srcdir)/putwchar.c'; fi`
+lib_a-stdio_ext.o: stdio_ext.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-stdio_ext.o `test -f 'stdio_ext.c' || echo '$(srcdir)/'`stdio_ext.c
+
+lib_a-stdio_ext.obj: stdio_ext.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-stdio_ext.obj `if test -f 'stdio_ext.c'; then $(CYGPATH_W) 'stdio_ext.c'; else $(CYGPATH_W) '$(srcdir)/stdio_ext.c'; fi`
+
lib_a-swprintf.o: swprintf.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-swprintf.o `test -f 'swprintf.c' || echo '$(srcdir)/'`swprintf.c
@@ -1788,6 +1798,7 @@ $(lpfx)sniprintf.$(oext): local.h
$(lpfx)sprintf.$(oext): local.h
$(lpfx)sscanf.$(oext): local.h
$(lpfx)stdio.$(oext): local.h
+$(lpfx)stdio_ext.$(oext): local.h
@NEWLIB_NANO_FORMATTED_IO_TRUE@$(lpfx)nano-svfprintf.$(oext): local.h nano-vfprintf_local.h
@NEWLIB_NANO_FORMATTED_IO_TRUE@$(lpfx)nano-svfscanf.$(oext): local.h nano-vfscanf_local.h
$(lpfx)svfiprintf.$(oext): local.h
Index: libc/stdio/stdio.tex
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/stdio.tex,v
retrieving revision 1.15
diff -u -p -r1.15 stdio.tex
--- libc/stdio/stdio.tex 3 Jul 2009 11:58:04 -0000 1.15
+++ libc/stdio/stdio.tex 11 Dec 2014 04:33:53 -0000
@@ -283,6 +283,9 @@ structure.
@include stdio/sscanf.def
@page
+@include stdio/stdio_ext.def
+
+@page
@include stdio/swprintf.def
@page
Index: libc/stdio/stdio_ext.c
===================================================================
RCS file: libc/stdio/stdio_ext.c
diff -N libc/stdio/stdio_ext.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libc/stdio/stdio_ext.c 11 Dec 2014 04:33:53 -0000
@@ -0,0 +1,149 @@
+/*
+FUNCTION
+<<__fbufsize>>, <<__fpending>>, <<__flbf>>, <<__freadable>>, <<__fwritable>> <<__freading>>, <<__fwriting>>,---access internals of FILE structure
+
+INDEX
+ __fbufsize
+INDEX
+ __fpending
+INDEX
+ __flbf
+INDEX
+ __freadable
+INDEX
+ __fwritable
+INDEX
+ __freading
+INDEX
+ __fwriting
+
+ANSI_SYNOPSIS
+ #include <stdio.h>
+ #include <stdio_ext.h>
+ size_t __fbufsize(FILE *<[fp]>);
+ size_t __fpending(FILE *<[fp]>);
+ int __flbf(FILE *<[fp]>);
+ int __freadable(FILE *<[fp]>);
+ int __fwritable(FILE *<[fp]>);
+ int __freading(FILE *<[fp]>);
+ int __fwriting(FILE *<[fp]>);
+
+DESCRIPTION
+These functions provides access to the internals of the FILE structure <[fp]>.
+
+RETURNS
+<<__fbufsize>> returns the number of bytes in the buffer of stream <[fp]>.
+
+<<__fpending>> returns the number of bytes in the output buffer of stream <[fp]>.
+
+<<__flbf>> returns nonzero if stream <[fp]> is line-buffered, and <<0>> if not.
+
+<<__freadable>> returns nonzero if stream <[fp]> may be read, and <<0>> if not.
+
+<<__fwritable>> returns nonzero if stream <[fp]> may be written, and <<0>> if not.
+
+<<__freading>> returns nonzero if stream <[fp]> if the last operation on
+it was a read, or if it read-only, and <<0>> if not.
+
+<<__fwriting>> returns nonzero if stream <[fp]> if the last operation on
+it was a write, or if it write-only, and <<0>> if not.
+
+PORTABILITY
+These functions originate from Solaris and are also provided by GNU libc.
+
+No supporting OS subroutines are required.
+*/
+
+#ifndef __rtems__
+
+#include <_ansi.h>
+#include <stdio.h>
+#include "local.h"
+
+/* Subroutine versions of the inline or macro functions. */
+
+size_t
+_DEFUN(__fbufsize, (fp),
+ FILE * fp)
+{
+ size_t result;
+ CHECK_INIT(_REENT, fp);
+ _newlib_flockfile_start (fp);
+ result = (size_t) fp->_bf._size;
+ _newlib_flockfile_end (fp);
+ return result;
+}
+
+size_t
+_DEFUN(__fpending, (fp),
+ FILE * fp)
+{
+ size_t result;
+ CHECK_INIT(_REENT, fp);
+ _newlib_flockfile_start (fp);
+ result = fp->_p - fp->_bf._base;
+ _newlib_flockfile_end (fp);
+ return result;
+}
+
+int
+_DEFUN(__flbf, (fp),
+ FILE * fp)
+{
+ int result;
+ CHECK_INIT(_REENT, fp);
+ _newlib_flockfile_start (fp);
+ result = ((fp->_flags & __SLBF) != 0);
+ _newlib_flockfile_end (fp);
+ return result;
+}
+
+int
+_DEFUN(__freadable, (fp),
+ FILE * fp)
+{
+ int result;
+ CHECK_INIT(_REENT, fp);
+ _newlib_flockfile_start (fp);
+ result = ((fp->_flags & (__SRD | __SRW)) != 0);
+ _newlib_flockfile_end (fp);
+ return result;
+}
+
+int
+_DEFUN(__fwritable, (fp),
+ FILE * fp)
+{
+ int result;
+ CHECK_INIT(_REENT, fp);
+ _newlib_flockfile_start (fp);
+ result = ((fp->_flags & (__SWR | __SRW)) != 0);
+ _newlib_flockfile_end (fp);
+ return result;
+}
+
+int
+_DEFUN(__freading, (fp),
+ FILE * fp)
+{
+ int result;
+ CHECK_INIT(_REENT, fp);
+ _newlib_flockfile_start (fp);
+ result = ((fp->_flags & __SRD) != 0);
+ _newlib_flockfile_end (fp);
+ return result;
+}
+
+int
+_DEFUN(__fwriting, (fp),
+ FILE * fp)
+{
+ int result;
+ CHECK_INIT(_REENT, fp);
+ _newlib_flockfile_start (fp);
+ result = ((fp->_flags & __SWR) != 0);
+ _newlib_flockfile_end (fp);
+ return result;
+}
+
+#endif /* __rtems__ */