This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: stdio_ext.h function implementations


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__ */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]