diff mbox series

[v2,2/2] Don't include libio.h from stdio.h.

Message ID 20180102034436.11037-2-zackw@panix.com
State New
Headers show
Series [v2,1/2] Avoid using libio internal symbols outside libio & stdio-common. | expand

Commit Message

Zack Weinberg Jan. 2, 2018, 3:44 a.m. UTC
The only thing stdio.h really needed libio.h for was the complete
definition of the FILE struct.  This is moved to
bits/types/struct_FILE.h, along with just enough ancillary definitions
for the inlines in bits/stdio.h.  stdio.h itself leaves FILE as an
opaque typedef; bits/types/struct_FILE.h will only be read when the
inlines are active.

Unlike the earlier patch where I had us stop shipping libio.h
entirely, I left the struct _IO_FILE / struct _IO_FILE_complete
distinction strictly alone in this patch, so it shouldn't break old
ABI compatibility.

	* libio/stdio.h: Don't include bits/libio.h.  Declare
        __underflow, __uflow, and __overflow here.

	* libio/bits/types/struct_FILE.h: New header containing the complete
	definitions of struct _IO_FILE and struct _IO_FILE_complete and a few
	ancillary definitions.
	* libio/Makefile: Install bits/types/struct_FILE.h.
	* libio/bits/stdio.h: Add multiple inclusion guard.  Include
	bits/types/struct_FILE.h.  Use getc, not _IO_getc; putc, not _IO_putc;
	__getc_unlocked_body, not _IO_getc_unlocked; __putc_unlocked_body, not
	_IO_putc_unlocked; __feof_unlocked_body, not _IO_feof_unlocked;
	__ferror_unlocked_body, not _IO_ferror_unlocked.
	* libio/bits/stdio2.h: Add multiple inclusion guard.
        Use getc_unlocked, not _IO_getc_unlocked.
	* libio/bits/libio.h: No longer allow inclusion from stdio.h.
	Move __HAVE_COLUMN and _IO_file_flags to the set of compatibility
	defines.  Get definition of _IO_FILE and fallback definition of
	_IO_lock_t from bits/types/struct_FILE.h. Use macros from
	bits/types/struct_FILE.h for _IO_getc_unlocked, _IO_putc_unlocked,
	_IO_feof_unlocked, and _IO_ferror_unlocked.
	Remove some #if 0 blocks and redundant prototypes.  Only provide
	non-thread-safe fallback definitions of several macros when
	neither _IO_MTSAFE_IO nor _LIBC is defined.

	* include/stdio_ext.h: Include bits/types/struct_FILE.h.
	* include/bits/types/struct_FILE.h: New wrapper.
---
 NEWS                             |  14 ++---
 include/bits/types/struct_FILE.h |   1 +
 include/stdio_ext.h              |   1 +
 libio/Makefile                   |   5 +-
 libio/bits/libio.h               | 113 +++++----------------------------------
 libio/bits/stdio.h               |  31 ++++++-----
 libio/bits/stdio2.h              |   7 ++-
 libio/bits/types/struct_FILE.h   | 103 +++++++++++++++++++++++++++++++++++
 libio/stdio.h                    |   7 ++-
 9 files changed, 159 insertions(+), 123 deletions(-)
 create mode 100644 include/bits/types/struct_FILE.h
 create mode 100644 libio/bits/types/struct_FILE.h

Comments

Andreas Schwab Jan. 2, 2018, 9:37 a.m. UTC | #1
On Jan 01 2018, Zack Weinberg <zackw@panix.com> wrote:

> diff --git a/libio/bits/types/struct_FILE.h b/libio/bits/types/struct_FILE.h
> new file mode 100644
> index 0000000000..a7598886f4
> --- /dev/null
> +++ b/libio/bits/types/struct_FILE.h
> @@ -0,0 +1,103 @@
> +#ifndef __struct_FILE_defined
> +#define __struct_FILE_defined 1
> +
> +/* Caution: The contents of this file are not part of the official
> +   stdio.h API.  However, much of it is part of the official *binary*
> +   interface, and therefore cannot be changed.  */
> +

Missing copyright header.

Andreas.
Zack Weinberg Jan. 8, 2018, 12:45 p.m. UTC | #2
On Mon, Jan 1, 2018 at 10:44 PM, Zack Weinberg <zackw@panix.com> wrote:
> The only thing stdio.h really needed libio.h for was the complete
> definition of the FILE struct.  This is moved to
> bits/types/struct_FILE.h, along with just enough ancillary definitions
> for the inlines in bits/stdio.h.  stdio.h itself leaves FILE as an
> opaque typedef; bits/types/struct_FILE.h will only be read when the
> inlines are active.

Ping?

zw
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index f0f4d8bcdd..019c2cc650 100644
--- a/NEWS
+++ b/NEWS
@@ -110,16 +110,16 @@  Deprecated and removed features, and other changes affecting compatibility:
 
 * The tilepro-*-linux-gnu configuration is no longer supported.
 
-* The nonstandard header files <libio.h> and <_G_config.h> are deprecated
-  and will be removed in a future release.  Software that is still using
-  either header should be updated to use standard <stdio.h> interfaces
-  instead.
+* The nonstandard header files <libio.h> and <_G_config.h> are deprecated.
+  <stdio.h> no longer includes either of them, and they will be removed in a
+  future release.  Software that is still using these headers, or their
+  contents, should be updated to use standard <stdio.h> interfaces instead.
 
   libio.h was originally the header for a set of supported GNU extensions,
   but they have not been maintained as such in many years, they are now
-  standing in the way of improvements to stdio, and we don't think there are
-  any remaining external users.  _G_config.h was never intended for public
-  use, but predates the bits convention.
+  standing in the way of improvements to stdio, and we are not aware of any
+  remaining external users.  _G_config.h was never intended for public use,
+  but predates the "bits" convention for private-but-installed headers.
 
 Changes to build and runtime requirements:
 
diff --git a/include/bits/types/struct_FILE.h b/include/bits/types/struct_FILE.h
new file mode 100644
index 0000000000..971407292b
--- /dev/null
+++ b/include/bits/types/struct_FILE.h
@@ -0,0 +1 @@ 
+#include <libio/bits/types/struct_FILE.h>
diff --git a/include/stdio_ext.h b/include/stdio_ext.h
index 29c6e68cdb..f4441def2a 100644
--- a/include/stdio_ext.h
+++ b/include/stdio_ext.h
@@ -2,6 +2,7 @@ 
 #include <stdio-common/stdio_ext.h>
 
 # ifndef _ISOMAC
+#  include <bits/types/struct_FILE.h>
 
 libc_hidden_proto (__fsetlocking)
 
diff --git a/libio/Makefile b/libio/Makefile
index 0e51833f62..309fa501d2 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -25,8 +25,9 @@  include ../Makeconfig
 headers	:= stdio.h libio.h _G_config.h \
 	   bits/stdio.h bits/libio.h bits/_G_config.h \
 	   bits/sys_errlist.h bits/stdio2.h bits/stdio-ldbl.h bits/libio-ldbl.h \
-	   bits/types/FILE.h bits/types/__FILE.h bits/types/__fpos_t.h \
-	   bits/types/__fpos64_t.h bits/types/cookie_io_functions_t.h
+	   bits/types/FILE.h bits/types/__FILE.h bits/types/struct_FILE.h \
+	   bits/types/__fpos_t.h bits/types/__fpos64_t.h \
+	   bits/types/cookie_io_functions_t.h
 
 routines	:=							      \
 	filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen      \
diff --git a/libio/bits/libio.h b/libio/bits/libio.h
index 08fa672b2a..feca5a0c87 100644
--- a/libio/bits/libio.h
+++ b/libio/bits/libio.h
@@ -28,11 +28,12 @@ 
 #ifndef _BITS_LIBIO_H
 #define _BITS_LIBIO_H 1
 
-#if !defined _STDIO_H && !defined _LIBIO_H && !defined _LIBIOP_H
-# error "Never include <bits/libio.h> directly; use <stdio.h> instead."
+#if !defined _LIBIO_H && !defined _LIBIOP_H
+# error "Never include <bits/libio.h> directly; use <libio.h> instead."
 #endif
 
 #include <stdio.h>
+#include <bits/types/struct_FILE.h>
 
 #include <bits/_G_config.h>
 /* ALL of these should be defined in _G_config.h */
@@ -50,9 +51,13 @@ 
 #define _IO_wint_t wint_t
 #define _IO_va_list __gnuc_va_list
 
+/* compatibility defines */
 #define _STDIO_USES_IOSTREAM
 #define _IO_UNIFIED_JUMPTABLES 1
+#define __HAVE_COLUMN
+#define _IO_file_flags _flags
 
+/* open modes */
 #define _IOS_INPUT	1
 #define _IOS_OUTPUT	2
 #define _IOS_ATEND	4
@@ -121,14 +126,7 @@ 
 #define _IO_BOOLALPHA 0200000
 
 
-struct _IO_jump_t;  struct _IO_FILE;
-
-/* During the build of glibc itself, _IO_lock_t will already have been
-   defined by internal headers.  */
-#ifndef _IO_lock_t_defined
-typedef void _IO_lock_t;
-#endif
-
+struct _IO_jump_t;
 
 /* A streammarker remembers a position in a buffer. */
 
@@ -139,16 +137,6 @@  struct _IO_marker {
  it points to _buf->Gbase()+_pos. FIXME comment */
   /* if _pos < 0, it points to _buf->eBptr()+_pos. FIXME comment */
   int _pos;
-#if 0
-    void set_streampos(streampos sp) { _spos = sp; }
-    void set_offset(int offset) { _pos = offset; _spos = (streampos)(-2); }
-  public:
-    streammarker(streambuf *sb);
-    ~streammarker();
-    int saving() { return  _spos == -2; }
-    int delta(streammarker&);
-    int delta();
-#endif
 };
 
 /* This is the structure from the libstdc++ codecvt class.  */
@@ -217,73 +205,6 @@  struct _IO_wide_data
 };
 #endif
 
-struct _IO_FILE {
-  int _flags;		/* High-order word is _IO_MAGIC; rest is flags. */
-#define _IO_file_flags _flags
-
-  /* The following pointers correspond to the C++ streambuf protocol. */
-  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
-  char* _IO_read_ptr;	/* Current read pointer */
-  char* _IO_read_end;	/* End of get area. */
-  char* _IO_read_base;	/* Start of putback+get area. */
-  char* _IO_write_base;	/* Start of put area. */
-  char* _IO_write_ptr;	/* Current put pointer. */
-  char* _IO_write_end;	/* End of put area. */
-  char* _IO_buf_base;	/* Start of reserve area. */
-  char* _IO_buf_end;	/* End of reserve area. */
-  /* The following fields are used to support backing up and undo. */
-  char *_IO_save_base; /* Pointer to start of non-current get area. */
-  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
-  char *_IO_save_end; /* Pointer to end of non-current get area. */
-
-  struct _IO_marker *_markers;
-
-  struct _IO_FILE *_chain;
-
-  int _fileno;
-#if 0
-  int _blksize;
-#else
-  int _flags2;
-#endif
-  _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */
-
-#define __HAVE_COLUMN /* temporary */
-  /* 1+column number of pbase(); 0 is unknown. */
-  unsigned short _cur_column;
-  signed char _vtable_offset;
-  char _shortbuf[1];
-
-  /*  char* _save_gptr;  char* _save_egptr; */
-
-  _IO_lock_t *_lock;
-#ifdef _IO_USE_OLD_IO_FILE
-};
-
-struct _IO_FILE_complete
-{
-  struct _IO_FILE _file;
-#endif
-#if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001
-  _IO_off64_t _offset;
-# if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
-  /* Wide character stream stuff.  */
-  struct _IO_codecvt *_codecvt;
-  struct _IO_wide_data *_wide_data;
-  struct _IO_FILE *_freeres_list;
-  void *_freeres_buf;
-# else
-  void *__pad1;
-  void *__pad2;
-  void *__pad3;
-  void *__pad4;
-# endif
-  size_t __pad5;
-  int _mode;
-  /* Make sure we don't get into trouble again.  */
-  char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
-#endif
-};
 
 #ifndef __cplusplus
 typedef struct _IO_FILE _IO_FILE;
@@ -325,9 +246,6 @@  extern void _IO_cookie_init (struct _IO_cookie_file *__cfile, int __read_write,
 extern "C" {
 #endif
 
-extern int __underflow (_IO_FILE *);
-extern int __uflow (_IO_FILE *);
-extern int __overflow (_IO_FILE *, int);
 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
 extern _IO_wint_t __wunderflow (_IO_FILE *);
 extern _IO_wint_t __wuflow (_IO_FILE *);
@@ -340,17 +258,12 @@  extern _IO_wint_t __woverflow (_IO_FILE *, _IO_wint_t);
 # define _IO_BE(expr, res) (expr)
 #endif
 
-#define _IO_getc_unlocked(_fp) \
-       (_IO_BE ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end, 0) \
-	? __uflow (_fp) : *(unsigned char *) (_fp)->_IO_read_ptr++)
+#define _IO_getc_unlocked(_fp) __getc_unlocked_body (_fp)
 #define _IO_peekc_unlocked(_fp) \
        (_IO_BE ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end, 0) \
 	  && __underflow (_fp) == EOF ? EOF \
 	: *(unsigned char *) (_fp)->_IO_read_ptr)
-#define _IO_putc_unlocked(_ch, _fp) \
-   (_IO_BE ((_fp)->_IO_write_ptr >= (_fp)->_IO_write_end, 0) \
-    ? __overflow (_fp, (unsigned char) (_ch)) \
-    : (unsigned char) (*(_fp)->_IO_write_ptr++ = (_ch)))
+#define _IO_putc_unlocked(_ch, _fp) __putc_unlocked_body (_ch, _fp)
 
 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
 # define _IO_getwc_unlocked(_fp) \
@@ -366,8 +279,8 @@  extern _IO_wint_t __woverflow (_IO_FILE *, _IO_wint_t);
    : (_IO_wint_t) (*(_fp)->_wide_data->_IO_write_ptr++ = (_wch)))
 #endif
 
-#define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0)
-#define _IO_ferror_unlocked(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0)
+#define _IO_feof_unlocked(_fp) __feof_unlocked_body (_fp)
+#define _IO_ferror_unlocked(_fp) __ferror_unlocked_body (_fp)
 
 extern int _IO_getc (_IO_FILE *__fp);
 extern int _IO_putc (int __c, _IO_FILE *__fp);
@@ -386,6 +299,7 @@  extern void (_IO_funlockfile) (_IO_FILE *) __THROW;
 extern int (_IO_ftrylockfile) (_IO_FILE *) __THROW;
 
 #define _IO_peekc(_fp) _IO_peekc_unlocked (_fp)
+#if !defined _LIBC && !defined _IO_MTSAFE_IO
 #define _IO_flockfile(_fp) /**/
 #define _IO_funlockfile(_fp) /**/
 #define _IO_ftrylockfile(_fp) /**/
@@ -395,6 +309,7 @@  extern int (_IO_ftrylockfile) (_IO_FILE *) __THROW;
 #ifndef _IO_cleanup_region_end
 #define _IO_cleanup_region_end(_Doit) /**/
 #endif
+#endif
 
 #define _IO_need_lock(_fp) \
   (((_fp)->_flags2 & _IO_FLAGS2_NEED_LOCK) != 0)
diff --git a/libio/bits/stdio.h b/libio/bits/stdio.h
index 1415709eb0..90b523a7be 100644
--- a/libio/bits/stdio.h
+++ b/libio/bits/stdio.h
@@ -16,10 +16,15 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _BITS_STDIO_H
+#define _BITS_STDIO_H 1
+
 #ifndef _STDIO_H
 # error "Never include <bits/stdio.h> directly; use <stdio.h> instead."
 #endif
 
+#include <bits/types/struct_FILE.h>
+
 #ifndef __extern_inline
 # define __STDIO_INLINE inline
 #else
@@ -43,7 +48,7 @@  vprintf (const char *__restrict __fmt, __gnuc_va_list __arg)
 __STDIO_INLINE int
 getchar (void)
 {
-  return _IO_getc (stdin);
+  return getc (stdin);
 }
 
 
@@ -52,7 +57,7 @@  getchar (void)
 __STDIO_INLINE int
 fgetc_unlocked (FILE *__fp)
 {
-  return _IO_getc_unlocked (__fp);
+  return __getc_unlocked_body (__fp);
 }
 # endif /* misc */
 
@@ -62,14 +67,14 @@  fgetc_unlocked (FILE *__fp)
 __STDIO_INLINE int
 getc_unlocked (FILE *__fp)
 {
-  return _IO_getc_unlocked (__fp);
+  return __getc_unlocked_body (__fp);
 }
 
 /* This is defined in POSIX.1:1996.  */
 __STDIO_INLINE int
 getchar_unlocked (void)
 {
-  return _IO_getc_unlocked (stdin);
+  return __getc_unlocked_body (stdin);
 }
 # endif	/* POSIX */
 
@@ -78,7 +83,7 @@  getchar_unlocked (void)
 __STDIO_INLINE int
 putchar (int __c)
 {
-  return _IO_putc (__c, stdout);
+  return putc (__c, stdout);
 }
 
 
@@ -87,7 +92,7 @@  putchar (int __c)
 __STDIO_INLINE int
 fputc_unlocked (int __c, FILE *__stream)
 {
-  return _IO_putc_unlocked (__c, __stream);
+  return __putc_unlocked_body (__c, __stream);
 }
 # endif /* misc */
 
@@ -97,14 +102,14 @@  fputc_unlocked (int __c, FILE *__stream)
 __STDIO_INLINE int
 putc_unlocked (int __c, FILE *__stream)
 {
-  return _IO_putc_unlocked (__c, __stream);
+  return __putc_unlocked_body (__c, __stream);
 }
 
 /* This is defined in POSIX.1:1996.  */
 __STDIO_INLINE int
 putchar_unlocked (int __c)
 {
-  return _IO_putc_unlocked (__c, stdout);
+  return __putc_unlocked_body (__c, stdout);
 }
 # endif	/* POSIX */
 
@@ -124,14 +129,14 @@  getline (char **__lineptr, size_t *__n, FILE *__stream)
 __STDIO_INLINE int
 __NTH (feof_unlocked (FILE *__stream))
 {
-  return _IO_feof_unlocked (__stream);
+  return __feof_unlocked_body (__stream);
 }
 
 /* Faster versions when locking is not required.  */
 __STDIO_INLINE int
 __NTH (ferror_unlocked (FILE *__stream))
 {
-  return _IO_ferror_unlocked (__stream);
+  return __ferror_unlocked_body (__stream);
 }
 # endif /* misc */
 
@@ -151,7 +156,7 @@  __NTH (ferror_unlocked (FILE *__stream))
 		       for (__cnt = (size_t) (size) * (size_t) (n);	      \
 			    __cnt > 0; --__cnt)				      \
 			 {						      \
-			   int __c = _IO_getc_unlocked (__stream);	      \
+			   int __c = getc_unlocked (__stream);		      \
 			   if (__c == EOF)				      \
 			     break;					      \
 			   *__ptr++ = __c;				      \
@@ -174,7 +179,7 @@  __NTH (ferror_unlocked (FILE *__stream))
 		       size_t __cnt;					      \
 		       for (__cnt = (size_t) (size) * (size_t) (n);	      \
 			    __cnt > 0; --__cnt)				      \
-			 if (_IO_putc_unlocked (*__ptr++, __stream) == EOF)   \
+			 if (putc_unlocked (*__ptr++, __stream) == EOF)	      \
 			   break;					      \
 		       ((size_t) (size) * (size_t) (n) - __cnt)		      \
 			/ (size_t) (size); })				      \
@@ -188,3 +193,5 @@  __NTH (ferror_unlocked (FILE *__stream))
 
 /* Define helper macro.  */
 #undef __STDIO_INLINE
+
+#endif /* bits/stdio.h.  */
diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h
index 0ab62ef913..11651506a6 100644
--- a/libio/bits/stdio2.h
+++ b/libio/bits/stdio2.h
@@ -16,6 +16,9 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _BITS_STDIO2_H
+#define _BITS_STDIO2_H 1
+
 #ifndef _STDIO_H
 # error "Never include <bits/stdio2.h> directly; use <stdio.h> instead."
 #endif
@@ -368,7 +371,7 @@  fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n,
 
       for (; __cnt > 0; --__cnt)
 	{
-	  int __c = _IO_getc_unlocked (__stream);
+	  int __c = getc_unlocked (__stream);
 	  if (__c == EOF)
 	    break;
 	  *__cptr++ = __c;
@@ -379,3 +382,5 @@  fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n,
   return __fread_unlocked_alias (__ptr, __size, __n, __stream);
 }
 #endif
+
+#endif /* bits/stdio2.h.  */
diff --git a/libio/bits/types/struct_FILE.h b/libio/bits/types/struct_FILE.h
new file mode 100644
index 0000000000..a7598886f4
--- /dev/null
+++ b/libio/bits/types/struct_FILE.h
@@ -0,0 +1,103 @@ 
+#ifndef __struct_FILE_defined
+#define __struct_FILE_defined 1
+
+/* Caution: The contents of this file are not part of the official
+   stdio.h API.  However, much of it is part of the official *binary*
+   interface, and therefore cannot be changed.  */
+
+#if defined _IO_USE_OLD_IO_FILE && !defined _LIBC
+# error "_IO_USE_OLD_IO_FILE should only be defined when building libc itself"
+#endif
+
+#if defined _IO_lock_t_defined && !defined _LIBC
+# error "_IO_lock_t_defined should only be defined when building libc itself"
+#endif
+
+#include <bits/types.h>
+
+struct _IO_FILE;
+struct _IO_marker;
+struct _IO_codecvt;
+struct _IO_wide_data;
+
+/* During the build of glibc itself, _IO_lock_t will already have been
+   defined by internal headers.  */
+#ifndef _IO_lock_t_defined
+typedef void _IO_lock_t;
+#endif
+
+/* Note: the tag name of this struct is _IO_FILE to preserve historic
+   C++ mangled names for functions taking FILE* arguments.  That name
+   should not be used in new code.  */
+struct _IO_FILE
+{
+  int _flags;		/* High-order word is _IO_MAGIC; rest is flags. */
+
+  /* The following pointers correspond to the C++ streambuf protocol. */
+  char *_IO_read_ptr;	/* Current read pointer */
+  char *_IO_read_end;	/* End of get area. */
+  char *_IO_read_base;	/* Start of putback+get area. */
+  char *_IO_write_base;	/* Start of put area. */
+  char *_IO_write_ptr;	/* Current put pointer. */
+  char *_IO_write_end;	/* End of put area. */
+  char *_IO_buf_base;	/* Start of reserve area. */
+  char *_IO_buf_end;	/* End of reserve area. */
+
+  /* The following fields are used to support backing up and undo. */
+  char *_IO_save_base; /* Pointer to start of non-current get area. */
+  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
+  char *_IO_save_end; /* Pointer to end of non-current get area. */
+
+  struct _IO_marker *_markers;
+
+  struct _IO_FILE *_chain;
+
+  int _fileno;
+  int _flags2;
+  __off_t _old_offset; /* This used to be _offset but it's too small.  */
+
+  /* 1+column number of pbase(); 0 is unknown. */
+  unsigned short _cur_column;
+  signed char _vtable_offset;
+  char _shortbuf[1];
+
+  _IO_lock_t *_lock;
+#ifdef _IO_USE_OLD_IO_FILE
+};
+
+struct _IO_FILE_complete
+{
+  struct _IO_FILE _file;
+#endif
+  __off64_t _offset;
+  /* Wide character stream stuff.  */
+  struct _IO_codecvt *_codecvt;
+  struct _IO_wide_data *_wide_data;
+  struct _IO_FILE *_freeres_list;
+  void *_freeres_buf;
+  size_t __pad5;
+  int _mode;
+  /* Make sure we don't get into trouble again.  */
+  char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
+};
+
+/* These macros are used by bits/stdio.h and libio.h.  */
+#define __getc_unlocked_body(_fp)					\
+  (__glibc_unlikely ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end)	\
+   ? __uflow (_fp) : *(unsigned char *) (_fp)->_IO_read_ptr++)
+
+#define __putc_unlocked_body(_ch, _fp)					\
+  (__glibc_unlikely ((_fp)->_IO_write_ptr >= (_fp)->_IO_write_end)	\
+   ? __overflow (_fp, (unsigned char) (_ch))				\
+   : (unsigned char) (*(_fp)->_IO_write_ptr++ = (_ch)))
+
+#define _IO_EOF_SEEN 0x10
+#define __feof_unlocked_body(_fp) (((_fp)->_flags & _IO_EOF_SEEN) != 0)
+
+#define _IO_ERR_SEEN 0x20
+#define __ferror_unlocked_body(_fp) (((_fp)->_flags & _IO_ERR_SEEN) != 0)
+
+#define _IO_USER_LOCK 0x8000
+/* Many more flag bits are defined internally.  */
+
+#endif
diff --git a/libio/stdio.h b/libio/stdio.h
index 1b4c58aff5..e761c126d5 100644
--- a/libio/stdio.h
+++ b/libio/stdio.h
@@ -845,8 +845,11 @@  extern void funlockfile (FILE *__stream) __THROW;
 # include <bits/getopt_posix.h>
 #endif
 
-/* Internal definitions used by optimizing inlines.  */
-#include <bits/libio.h>
+/* Slow-path routines used by the optimized inline functions in
+   bits/stdio.h.  */
+extern int __underflow (FILE *);
+extern int __uflow (FILE *);
+extern int __overflow (FILE *, int);
 
 /* If we are compiling with optimizing read this file.  It contains
    several optimizing inline functions and macros.  */