summary refs log tree commit diff
path: root/libio
diff options
context:
space:
mode:
Diffstat (limited to 'libio')
-rw-r--r--libio/Makefile12
-rw-r--r--libio/filedoalloc.c2
-rw-r--r--libio/fileops.c8
-rw-r--r--libio/genops.c4
-rw-r--r--libio/iolibio.h19
-rw-r--r--libio/iopopen.c2
-rw-r--r--libio/iovsprintf.c2
-rw-r--r--libio/iovsscanf.c2
-rw-r--r--libio/libio.h15
-rw-r--r--libio/libioP.h185
-rw-r--r--libio/memstream.c12
-rw-r--r--libio/stdio.h3
-rw-r--r--libio/strfile.h20
-rw-r--r--libio/vasprintf.c12
-rw-r--r--libio/vsnprintf.c2
15 files changed, 231 insertions, 69 deletions
diff --git a/libio/Makefile b/libio/Makefile
index 4266ad4e59..53a1d7d843 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -12,9 +12,9 @@
 # Library General Public License for more details.
 
 # You should have received a copy of the GNU Library General Public
-# License along with the GNU C Library; see the file COPYING.LIB.  If
-# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-# Cambridge, MA 02139, USA.
+# License along with the GNU C Library; see the file COPYING.LIB.  If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
 
 #
 #	Specific makefile for libio.
@@ -26,7 +26,7 @@ headers	:= stdio.h libio.h _G_config.h
 routines	:=							      \
 	filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen      \
 	iofopncook iofprintf iofputs iofread iofsetpos ioftell		      \
-	iofwrite iogetdelim iogetline iogets iopadn iopopen ioprims ioputs    \
+	iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs	      \
 	ioseekoff ioseekpos iosetbuffer iosetvbuf iosprintf ioungetc	      \
 	iovsprintf iovsscanf						      \
 									      \
@@ -40,6 +40,8 @@ all: # Make this the default target; it will be defined in Rules.
 
 include ../Makeconfig
 
+CPPFLAGS-.o += -DIO_DEBUG
+
 ifneq (,$(filter %REENTRANT, $(defines)))
 routines += clearerr_u feof_u ferror_u fputc_u getc_u getchar_u		      \
 	    iofflush_u putc_u putchar_u peekc
@@ -48,7 +50,7 @@ CPPFLAGS += -D_IO_MTSAFE_IO
 endif
 
 aux	:=								      \
-	cleanup fileops genops stdfiles stdio strops
+	fileops genops stdfiles stdio strops
 
 distribute := iolibio.h libioP.h strfile.h Banner
 
diff --git a/libio/filedoalloc.c b/libio/filedoalloc.c
index 045bff697d..eee489b825 100644
--- a/libio/filedoalloc.c
+++ b/libio/filedoalloc.c
@@ -71,12 +71,14 @@ DEFUN(_IO_file_doallocate, (fp),
   register char *p;
   struct stat st;
 
+#ifndef _LIBC
   /* If _IO_cleanup_registration_needed is non-zero, we should call the
      function it points to.  This is to make sure _IO_cleanup gets called
      on exit.  We call it from _IO_file_doallocate, since that is likely
      to get called by any program that does buffered I/O. */
   if (_IO_cleanup_registration_needed)
     (*_IO_cleanup_registration_needed)();
+#endif
 
   if (fp->_fileno < 0 || _IO_SYSSTAT (fp, &st) < 0)
     {
diff --git a/libio/fileops.c b/libio/fileops.c
index d3f4831e2d..ce0e2bb524 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -47,7 +47,6 @@ extern int errno;
    The position in the buffer that corresponds to the position
    in external file system is normally _IO_read_end, except in putback
    mode, when it is _IO_save_end.
-   when it is _IO_save_end.
    If the field _fb._offset is >= 0, it gives the offset in
    the file as a whole corresponding to eGptr(). (?)
 
@@ -185,7 +184,7 @@ DEFUN(_IO_file_fopen, (fp, filename, mode),
   _IO_mask_flags(fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
   if (read_write & _IO_IS_APPENDING)
     if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
-	== _IO_pos_BAD)
+	== _IO_pos_BAD && errno != ESPIPE)
       return NULL;
   _IO_link_in(fp);
   return fp;
@@ -200,7 +199,12 @@ DEFUN(_IO_file_attach, (fp, fd),
   fp->_fileno = fd;
   fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
   fp->_flags |= _IO_DELETE_DONT_CLOSE;
+  /* Get the current position of the file. */
+  /* We have to do that since that may be junk. */
   fp->_offset = _IO_pos_BAD;
+  if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
+      == _IO_pos_BAD && errno != ESPIPE)
+    return NULL;
   return fp;
 }
 
diff --git a/libio/genops.c b/libio/genops.c
index fc4c61d9a4..3a58cd2eaf 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -861,3 +861,7 @@ __io_defs io_defs__;
 #ifdef weak_alias
 weak_alias (_IO_cleanup, _cleanup)
 #endif
+
+#ifdef text_set_element
+text_set_element(__libc_atexit, _cleanup);
+#endif
diff --git a/libio/iolibio.h b/libio/iolibio.h
index 92df6a6fd2..ca863b51b3 100644
--- a/libio/iolibio.h
+++ b/libio/iolibio.h
@@ -56,3 +56,22 @@ extern _IO_FILE* _IO_popen __P((const char*, const char*));
 #ifdef __cplusplus
 }
 #endif
+
+#define _IO_open	__open
+#define _IO_close	__close
+#define	_IO_fork	__fork
+#define	_IO_fcntl	__fcntl
+#define _IO__exit	_exit
+#define _IO_read	__read
+#define _IO_write	__write
+#define _IO_lseek	__lseek
+#define	_IO_getdtablesize	__getdtablesize
+#define _IO_pipe	__pipe
+#define _IO_dup2	__dup2
+#define _IO_execl	execl
+#define _IO_waitpid	__waitpid
+#define _IO_stat        __stat
+#define _IO_getpid      __getpid
+#define _IO_geteuid     __geteuid
+#define _IO_getegid     __getegid
+#define _IO_fstat	__fstat
diff --git a/libio/iopopen.c b/libio/iopopen.c
index dc1e74d3eb..5703c99d47 100644
--- a/libio/iopopen.c
+++ b/libio/iopopen.c
@@ -123,7 +123,7 @@ DEFUN(_IO_proc_open, (fp, command, mode),
 	  proc_file_chain = proc_file_chain->next;
 	}
 
-      _IO_execl("/bin/sh", "sh", "-c", command, NULL);
+      _IO_execl("/bin/sh", "sh", "-c", command, (char *) 0);
       _IO__exit(127);
     }
   _IO_close(child_end);
diff --git a/libio/iovsprintf.c b/libio/iovsprintf.c
index b2e8b67a96..f0c9889724 100644
--- a/libio/iovsprintf.c
+++ b/libio/iovsprintf.c
@@ -38,7 +38,7 @@ _IO_vsprintf (string, format, args)
   int ret;
 
 #ifdef _IO_MTSAFE_IO
-  sf._f._lock = &lock;
+  sf._sbf._f._lock = &lock;
 #endif
   _IO_init ((_IO_FILE *) &sf, 0);
   _IO_JUMPS ((_IO_FILE *) &sf) = &_IO_str_jumps;
diff --git a/libio/iovsscanf.c b/libio/iovsscanf.c
index 6e7d8c59e2..473b714f21 100644
--- a/libio/iovsscanf.c
+++ b/libio/iovsscanf.c
@@ -32,7 +32,7 @@ DEFUN(_IO_vsscanf, (string, format, args),
   _IO_strfile sf;
 #ifdef _IO_MTSAFE_IO
   _IO_lock_t lock;
-  sf._f._lock = &lock;
+  sf._sbf._f._lock = &lock;
 #endif
   _IO_init((_IO_FILE*)&sf, 0);
   _IO_JUMPS((_IO_FILE*)&sf) = &_IO_str_jumps;
diff --git a/libio/libio.h b/libio/libio.h
index 7dd47db9fa..acc34c0d7a 100644
--- a/libio/libio.h
+++ b/libio/libio.h
@@ -52,11 +52,15 @@ the executable file might be covered by the GNU General Public License. */
 #endif
 
 #ifndef __P
+#if _G_HAVE_SYS_CDEFS
+#include <sys/cdefs.h>
+#else
 #ifdef __STDC__
 #define __P(protos) protos
 #else
 #define __P(protos) ()
 #endif
+#endif
 #endif /*!__P*/
 
 /* For backward compatibility */
@@ -79,12 +83,16 @@ the executable file might be covered by the GNU General Public License. */
 #define EOF (-1)
 #endif
 #ifndef NULL
-#if !defined(__cplusplus) || defined(__GNUC__)
+#ifdef __GNUG__
+#define NULL (__null)
+#else
+#if !defined(__cplusplus)
 #define NULL ((void*)0)
 #else
 #define NULL (0)
 #endif
 #endif
+#endif
 
 #define _IOS_INPUT	1
 #define _IOS_OUTPUT	2
@@ -183,6 +191,7 @@ struct _IO_FILE {
 #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. */
@@ -200,10 +209,6 @@ struct _IO_FILE {
 
   struct _IO_FILE *_chain;
 
-#if  !_IO_UNIFIED_JUMPTABLES
-  struct _IO_jump_t *_jumps; /* Jump table */
-#endif
-
   int _fileno;
   int _blksize;
   _IO_off_t _offset;
diff --git a/libio/libioP.h b/libio/libioP.h
index d3c871fbeb..008f9b7edf 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -57,71 +57,180 @@ extern "C" {
 #define _IO_seek_cur 1
 #define _IO_seek_end 2
 
-typedef int (*_IO_overflow_t) __P((_IO_FILE*, int));
-typedef int (*_IO_underflow_t) __P((_IO_FILE*));
-typedef _IO_size_t (*_IO_xsputn_t) __P((_IO_FILE*,const void*,_IO_size_t));
-typedef _IO_size_t (*_IO_xsgetn_t) __P((_IO_FILE*, void*, _IO_size_t));
-typedef _IO_ssize_t (*_IO_read_t) __P((_IO_FILE*, void*, _IO_ssize_t));
-typedef _IO_ssize_t (*_IO_write_t) __P((_IO_FILE*,const void*,_IO_ssize_t));
-typedef int (*_IO_stat_t) __P((_IO_FILE*, void*));
-typedef _IO_fpos_t (*_IO_seek_t) __P((_IO_FILE*, _IO_off_t, int));
-typedef int (*_IO_doallocate_t) __P((_IO_FILE*));
-typedef int (*_IO_pbackfail_t) __P((_IO_FILE*, int));
-typedef _IO_FILE* (*_IO_setbuf_t) __P((_IO_FILE*, char *, _IO_ssize_t));
-typedef int (*_IO_sync_t) __P((_IO_FILE*));
-typedef void (*_IO_finish_t) __P((_IO_FILE*)); /* finalize */
-typedef int (*_IO_close_t) __P((_IO_FILE*)); /* finalize */
-typedef _IO_fpos_t (*_IO_seekoff_t) __P((_IO_FILE*, _IO_off_t, int, int));
-
-/* The _IO_seek_cur and _IO_seek_end options are not allowed. */
-typedef _IO_fpos_t (*_IO_seekpos_t) __P((_IO_FILE*, _IO_fpos_t, int));
+/* THE JUMPTABLE FUNCTIONS.
+
+ * The _IO_FILE type is used to implement the FILE type in GNU libc,
+ * as well as the streambuf class in GNU iostreams for C++.
+ * These are all the same, just used differently.
+ * An _IO_FILE (or FILE) object is allows followed by a pointer to
+ * a jump table (of pointers to functions).  The pointer is accessed
+ * with the _IO_JUMPS macro.  The jump table has a eccentric format,
+ * so as to be compatible with the layout of a C++ virtual function table.
+ * (as implemented by g++).  When a pointer to a steambuf object is
+ * coerced to an (_IO_FILE*), then _IO_JUMPS on the result just
+ * happens to point to the virtual function table of the streambuf.
+ * Thus the _IO_JUMPS function table used for C stdio/libio does
+ * double duty as the virtual functiuon table for C++ streambuf.
+ *
+ * The entries in the _IO_JUMPS function table (and hence also the
+ * virtual functions of a streambuf) are described below.
+ * The first parameter of each function entry is the _IO_FILE/streambuf
+ * object being acted on (i.e. the 'this' parameter).
+ */
 
-#if  !_IO_UNIFIED_JUMPTABLES
-#define _IO_JUMPS(THIS) (THIS)->_jumps
-#else
 #define _IO_JUMPS(THIS) ((struct _IO_FILE_plus*)(THIS))->vtable
-#endif
-
-#if  !_IO_UNIFIED_JUMPTABLES
+#ifdef _G_USING_THUNKS
 #define JUMP_FIELD(TYPE, NAME) TYPE NAME
 #define JUMP0(FUNC, THIS) _IO_JUMPS(THIS)->FUNC(THIS)
 #define JUMP1(FUNC, THIS, X1) _IO_JUMPS(THIS)->FUNC(THIS, X1)
 #define JUMP2(FUNC, THIS, X1, X2) _IO_JUMPS(THIS)->FUNC(THIS, X1, X2)
-#define JUMP3(FUNC, THIS, X1, X2, X3) _IO_JUMPS(THIS)->FUNC(THIS, X1, X2, X3)
+#define JUMP3(FUNC, THIS, X1,X2,X3) _IO_JUMPS(THIS)->FUNC(THIS, X1,X2, X3)
 #define JUMP_INIT(NAME, VALUE) VALUE
+#define JUMP_INIT_DUMMY JUMP_INIT(dummy, 0), JUMP_INIT(dummy2, 0)
 #else
+/* These macros will change when we re-implement vtables to use "thunks"! */
 #define JUMP_FIELD(TYPE, NAME) struct { short delta1, delta2; TYPE pfn; } NAME
 #define JUMP0(FUNC, THIS) _IO_JUMPS(THIS)->FUNC.pfn(THIS)
 #define JUMP1(FUNC, THIS, X1) _IO_JUMPS(THIS)->FUNC.pfn(THIS, X1)
 #define JUMP2(FUNC, THIS, X1, X2) _IO_JUMPS(THIS)->FUNC.pfn(THIS, X1, X2)
 #define JUMP3(FUNC, THIS, X1,X2,X3) _IO_JUMPS(THIS)->FUNC.pfn(THIS, X1,X2, X3)
 #define JUMP_INIT(NAME, VALUE) {0, 0, VALUE}
-#endif
 #define JUMP_INIT_DUMMY JUMP_INIT(dummy, 0)
+#endif
 
+/* The 'finish' function does any final cleaning up of an _IO_FILE object.
+   It does not delete (free) it, but does everything else to finalize it/
+   It matches the streambuf::~streambuf virtual destructor.  */
+typedef void (*_IO_finish_t) __P((_IO_FILE*)); /* finalize */
 #define _IO_FINISH(FP) JUMP0(__finish, FP)
+
+/* The 'overflow' hook flushes the buffer.
+   The second argument is a character, or EOF.
+   It matches the streambuf::overflow virtual function. */
+typedef int (*_IO_overflow_t) __P((_IO_FILE*, int));
 #define _IO_OVERFLOW(FP, CH) JUMP1(__overflow, FP, CH)
+
+/* The 'underflow' hook tries to fills the get buffer.
+   It returns the next character (as an unsigned char) or EOF.  The next
+   character remains in the get buffer, and the get postion is not changed.
+   It matches the streambuf::underflow virtual function. */
+typedef int (*_IO_underflow_t) __P((_IO_FILE*));
 #define _IO_UNDERFLOW(FP) JUMP0(__underflow, FP)
+
+/* The 'uflow' hook returns the next character in the input stream
+   (cast to unsigned char), and increments the read position;
+   EOF is returned on failure.
+   It matches the streambuf::uflow virtual function, which is not in the
+   cfront implementation, but was added to C++ by the ANSI/ISO committee. */
 #define _IO_UFLOW(FP) JUMP0(__uflow, FP)
+
+/* The 'pbackfail' hook handles backing up.
+   It matches the streambuf::pbackfail virtual function. */
+typedef int (*_IO_pbackfail_t) __P((_IO_FILE*, int));
 #define _IO_PBACKFAIL(FP, CH) JUMP1(__pbackfail, FP, CH)
+
+/* The 'xsputn' hook writes upto N characters from buffer DATA.
+   Returns the number of character actually written.
+   It matches the streambuf::xsputn virtual function. */
+typedef _IO_size_t (*_IO_xsputn_t)
+  __P((_IO_FILE *FP, const void *DATA, _IO_size_t N));
 #define _IO_XSPUTN(FP, DATA, N) JUMP2(__xsputn, FP, DATA, N)
+
+/* The 'xsgetn' hook reads upto N characters into buffer DATA.
+   Returns the number of character actually read.
+   It matches the streambuf::xsgetn virtual function. */
+typedef _IO_size_t (*_IO_xsgetn_t) __P((_IO_FILE*FP, void*DATA, _IO_size_t N));
 #define _IO_XSGETN(FP, DATA, N) JUMP2(__xsgetn, FP, DATA, N)
+
+/* The 'seekoff' hook moves the stream position to a new position
+   relative to the start of the file (if DIR==0), the current position
+   (MODE==1), or the end of the file (MODE==2).
+   It matches the streambuf::seekoff virtual function.
+   It is also used for the ANSI fseek function. */
+typedef _IO_fpos_t (*_IO_seekoff_t)
+  __P((_IO_FILE* FP, _IO_off_t OFF, int DIR, int MODE));
 #define _IO_SEEKOFF(FP, OFF, DIR, MODE) JUMP3(__seekoff, FP, OFF, DIR, MODE)
+
+/* The 'seekpos' hook also moves the stream position,
+   but to an absolute position given by a fpos_t (seekpos).
+   It matches the streambuf::seekpos virtual function.
+   It is also used for the ANSI fgetpos and fsetpos functions.  */
+/* The _IO_seek_cur and _IO_seek_end options are not allowed. */
+typedef _IO_fpos_t (*_IO_seekpos_t) __P((_IO_FILE*, _IO_fpos_t, int));
 #define _IO_SEEKPOS(FP, POS, FLAGS) JUMP2(__seekpos, FP, POS, FLAGS)
+
+/* The 'setbuf' hook gives a buffer to the file.
+   It matches the streambuf::setbuf virtual function. */
+typedef _IO_FILE* (*_IO_setbuf_t) __P((_IO_FILE*, char *, _IO_ssize_t));
 #define _IO_SETBUF(FP, BUFFER, LENGTH) JUMP2(__setbuf, FP, BUFFER, LENGTH)
+
+/* The 'sync' hook attempts to synchronize the internal data structures
+   of the file with the external state.
+   It matches the streambuf::sync virtual function. */
+typedef int (*_IO_sync_t) __P((_IO_FILE*));
 #define _IO_SYNC(FP) JUMP0(__sync, FP)
+
+/* The 'doallocate' hook is used to tell the file to allocate a buffer.
+   It matches the streambuf::doallocate virtual function, which is not
+   in the ANSI/ISO C++ standard, but is part traditional implementations. */
+typedef int (*_IO_doallocate_t) __P((_IO_FILE*));
 #define _IO_DOALLOCATE(FP) JUMP0(__doallocate, FP)
+
+/* The following four hooks (sysread, syswrite, sysclose, sysseek, and
+   sysstat) are low-level hooks specific to this implementation.
+   There is no correspondance in the ANSI/ISO C++ standard library.
+   The hooks basically correspond to the Unix system functions
+   (read, write, close, lseek, and stat) except that a _IO_FILE*
+   parameter is used instead of a integer file descriptor;  the default
+   implementation used for normal files just calls those functions.
+   The advantage of overriding these functions instead of the higher-level
+   ones (underflow, overflow etc) is that you can leave all the buffering
+   higher-level functions.  */
+
+/* The 'sysread' hook is used to read data from the external file into
+   an existing buffer.  It generalizes the Unix read(2) function.
+   It matches the streambuf::sys_read virtual function, which is
+   specific to this implementaion. */
+typedef _IO_ssize_t (*_IO_read_t) __P((_IO_FILE*, void*, _IO_ssize_t));
 #define _IO_SYSREAD(FP, DATA, LEN) JUMP2(__read, FP, DATA, LEN)
+
+/* The 'syswrite' hook is used to write data from an existing buffer
+   to an external file.  It generalizes the Unix write(2) function.
+   It matches the streambuf::sys_write virtual function, which is
+   specific to this implementaion. */
+typedef _IO_ssize_t (*_IO_write_t) __P((_IO_FILE*,const void*,_IO_ssize_t));
 #define _IO_SYSWRITE(FP, DATA, LEN) JUMP2(__write, FP, DATA, LEN)
+
+/* The 'sysseek' hook is used to re-position an external file.
+   It generalizes the Unix lseek(2) function.
+   It matches the streambuf::sys_seek virtual function, which is
+   specific to this implementaion. */
+typedef _IO_fpos_t (*_IO_seek_t) __P((_IO_FILE*, _IO_off_t, int));
 #define _IO_SYSSEEK(FP, OFFSET, MODE) JUMP2(__seek, FP, OFFSET, MODE)
+
+/* The 'sysclose' hook is used to finalize (close, finish up) an
+   external file.  It generalizes the Unix close(2) function.
+   It matches the streambuf::sys_close virtual function, which is
+   specific to this implementation. */
+typedef int (*_IO_close_t) __P((_IO_FILE*)); /* finalize */
 #define _IO_SYSCLOSE(FP) JUMP0(__close, FP)
+
+/* The 'sysstat' hook is used to get information about an external file
+   into a struct stat buffer.  It generalizes the Unix fstat(2) call.
+   It matches the streambuf::sys_stat virtual function, which is
+   specific to this implementaion. */
+typedef int (*_IO_stat_t) __P((_IO_FILE*, void*));
 #define _IO_SYSSTAT(FP, BUF) JUMP1(__stat, FP, BUF)
 
+
 #define _IO_CHAR_TYPE char /* unsigned char ? */
 #define _IO_INT_TYPE int
 
 struct _IO_jump_t {
     JUMP_FIELD(_G_size_t, __dummy);
+#ifdef _G_USING_THUNKS
+    JUMP_FIELD(_G_size_t, __dummy2);
+#endif
     JUMP_FIELD(_IO_finish_t, __finish);
     JUMP_FIELD(_IO_overflow_t, __overflow);
     JUMP_FIELD(_IO_underflow_t, __underflow);
@@ -147,16 +256,13 @@ struct _IO_jump_t {
 };
 
 /* We always allocate an extra word following an _IO_FILE.
+   This contains a pointer to the function jump table used.
    This is for compatibility with C++ streambuf; the word can
    be used to smash to a pointer to a virtual function table. */
 
 struct _IO_FILE_plus {
   _IO_FILE file;
-#if _IO_UNIFIED_JUMPTABLES
   const struct _IO_jump_t *vtable;
-#else
-  const void *vtable;
-#endif
 };
 
 /* Generic functions */
@@ -225,7 +331,7 @@ extern void _IO_flush_all_linebuffered __P((void));
 #define _IO_have_backup(fp) ((fp)->_IO_save_base != NULL)
 #define _IO_in_backup(fp) ((fp)->_flags & _IO_IN_BACKUP)
 #define _IO_have_markers(fp) ((fp)->_markers != NULL)
-#define _IO_blen(p) ((fp)->_IO_buf_end - (fp)->_IO_buf_base)
+#define _IO_blen(fp) ((fp)->_IO_buf_end - (fp)->_IO_buf_base)
 
 /* Jumptable functions for files. */
 
@@ -290,12 +396,16 @@ extern void (*_IO_cleanup_registration_needed) __P ((void));
 #define EOF (-1)
 #endif
 #ifndef NULL
-#if !defined(__cplusplus) || defined(__GNUC__)
+#ifdef __GNUG__
+#define NULL (__null)
+#else
+#if !defined(__cplusplus)
 #define NULL ((void*)0)
 #else
 #define NULL (0)
 #endif
 #endif
+#endif
 
 #define FREE_BUF(_B) free(_B)
 #define ALLOC_BUF(_S) (char*)malloc(_S)
@@ -337,22 +447,17 @@ extern int _IO_vscanf __P((const char *, _IO_va_list));
 }
 #endif
 
-#if  _IO_UNIFIED_JUMPTABLES
-#define _IO_FJUMP /* nothing */
-#else
-#define _IO_FJUMP &_IO_file_jumps,
-#endif
 #ifdef _IO_MTSAFE_IO
 /* check following! */
 #define FILEBUF_LITERAL(CHAIN, FLAGS, FD) \
        { _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+FLAGS, \
-         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, _IO_FJUMP FD, \
+         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, FD, \
 	   0, 0, 0, 0, { 0 }, &_IO_stdfile_##FD##_lock }
 #else
 /* check following! */
 #define FILEBUF_LITERAL(CHAIN, FLAGS, FD) \
        { _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+FLAGS, \
-	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, _IO_FJUMP FD }
+	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, FD }
 #endif
 
 /* VTABLE_LABEL defines NAME as of the CLASS class.
@@ -402,7 +507,7 @@ extern struct _IO_fake_stdiobuf _IO_stdin_buf, _IO_stdout_buf, _IO_stderr_buf;
 #define MAYBE_SET_EINVAL /* nothing */
 #endif
 
-#ifdef DEBUG
+#ifdef IO_DEBUG
 #define CHECK_FILE(FILE,RET) \
 	if ((FILE) == NULL) { MAYBE_SET_EINVAL; return RET; } \
 	else { COERCE_FILE(FILE); \
diff --git a/libio/memstream.c b/libio/memstream.c
index 8f9c8ac92c..ddcce676cb 100644
--- a/libio/memstream.c
+++ b/libio/memstream.c
@@ -77,21 +77,21 @@ open_memstream (bufloc, sizeloc)
   if (new_f == NULL)
     return NULL;
 #ifdef _IO_MTSAFE_IO
-  new_f->fp._sf._f._lock = &new_f->lock;
+  new_f->fp._sf._sbf._f._lock = &new_f->lock;
 #endif
 
   buf = ALLOC_BUF (_IO_BUFSIZ);
-  _IO_init (&new_f->fp._sf._f, 0);
-  _IO_JUMPS (&new_f->fp._sf._f) = &_IO_mem_jumps;
-  _IO_str_init_static (&new_f->fp._sf._f, buf, _IO_BUFSIZ, buf);
-  new_f->fp._sf._f._flags &= ~_IO_USER_BUF;
+  _IO_init (&new_f->fp._sf._sbf._f, 0);
+  _IO_JUMPS (&new_f->fp._sf._sbf._f) = &_IO_mem_jumps;
+  _IO_str_init_static (&new_f->fp._sf._sbf._f, buf, _IO_BUFSIZ, buf);
+  new_f->fp._sf._sbf._f._flags &= ~_IO_USER_BUF;
   new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc;
   new_f->fp._sf._s._free_buffer = (_IO_free_type) free;
 
   new_f->fp.bufloc = bufloc;
   new_f->fp.sizeloc = sizeloc;
 
-  return &new_f->fp._sf._f;
+  return &new_f->fp._sf._sbf._f;
 }
 
 
diff --git a/libio/stdio.h b/libio/stdio.h
index 75d22f94c0..ba5fa5438e 100644
--- a/libio/stdio.h
+++ b/libio/stdio.h
@@ -73,7 +73,10 @@ typedef _IO_fpos_t fpos_t;
 
 #include <stdio_lim.h>
 
+#ifdef	__USE_SVID
+/* Default path prefix for `tempnam' and `tmpnam'.  */
 #define P_tmpdir      "/tmp"
+#endif
 
 /* For use by debuggers. These are linked in if printf or fprintf are used. */
 extern FILE *stdin, *stdout, *stderr; /* TODO */
diff --git a/libio/strfile.h b/libio/strfile.h
index 4934a06e3c..76044f8927 100644
--- a/libio/strfile.h
+++ b/libio/strfile.h
@@ -36,9 +36,27 @@ struct _IO_str_fields
   _IO_free_type _free_buffer;
 };
 
-typedef struct _IO_strfile_
+/* This is needed for the Irix6 N32 ABI, which has a 64 bit off_t type,
+   but a 32 bit pointer type.  In this case, we get 4 bytes of padding
+   after the vtable pointer.  Putting them in a structure together solves
+   this problem.  */
+
+struct _IO_streambuf
 {
   struct _IO_FILE _f;
   const void *_vtable;
+};
+
+typedef struct _IO_strfile_
+{
+  struct _IO_streambuf _sbf;
   struct _IO_str_fields _s;
 } _IO_strfile;
+
+/* dynamic: set when the array object is allocated (or reallocated)  as
+   necessary to hold a character sequence that can change in length. */
+#define _IO_STR_DYNAMIC(FP) ((FP)->_s._allocate_buffer != (_IO_alloc_type)0)
+
+/* frozen: set when the program has requested that the array object not
+   be altered, reallocated, or freed. */
+#define _IO_STR_FROZEN(FP) ((FP)->_f._IO_file_flags & _IO_USER_BUF)
diff --git a/libio/vasprintf.c b/libio/vasprintf.c
index 57a3b08eba..f8dba80c38 100644
--- a/libio/vasprintf.c
+++ b/libio/vasprintf.c
@@ -46,22 +46,22 @@ _IO_vasprintf (result_ptr, format, args)
   if (string == NULL)
     return -1;
 #ifdef _IO_MTSAFE_IO
-  sf._f._lock = &lock;
+  sf._sbf._f._lock = &lock;
 #endif
   _IO_init((_IO_FILE*)&sf, 0);
   _IO_JUMPS((_IO_FILE*)&sf) = &_IO_str_jumps;
   _IO_str_init_static ((_IO_FILE*)&sf, string, init_string_size, string);
-  sf._f._flags &= ~_IO_USER_BUF;
+  sf._sbf._f._flags &= ~_IO_USER_BUF;
   sf._s._allocate_buffer = (_IO_alloc_type)malloc;
   sf._s._free_buffer = (_IO_free_type)free;
   ret = _IO_vfprintf((_IO_FILE*)&sf, format, args);
   if (ret < 0)
     return ret;
-  *result_ptr = (char*)realloc(sf._f._IO_buf_base,
-			       (sf._f._IO_write_ptr - sf._f._IO_write_base) +1);
+  *result_ptr = (char*)realloc(sf._sbf._f._IO_buf_base,
+			       (sf._sbf._f._IO_write_ptr - sf._sbf._f._IO_write_base) +1);
   if (*result_ptr == NULL)
-    *result_ptr = sf._f._IO_buf_base;
-  (*result_ptr)[sf._f._IO_write_ptr-sf._f._IO_write_base] = '\0';
+    *result_ptr = sf._sbf._f._IO_buf_base;
+  (*result_ptr)[sf._sbf._f._IO_write_ptr-sf._sbf._f._IO_write_base] = '\0';
   return ret;
 }
 weak_alias (_IO_vasprintf, vasprintf)
diff --git a/libio/vsnprintf.c b/libio/vsnprintf.c
index 9f767b5b06..9ec06914c0 100644
--- a/libio/vsnprintf.c
+++ b/libio/vsnprintf.c
@@ -36,7 +36,7 @@ _IO_vsnprintf (string, maxlen, format, args)
   int ret;
 #ifdef _IO_MTSAFE_IO
   _IO_lock_t lock;
-  sf._f._lock = &lock;
+  sf._sbf._f._lock = &lock;
 #endif
   _IO_init ((_IO_FILE *) &sf, 0);
   _IO_JUMPS ((_IO_FILE *) &sf) = &_IO_str_jumps;