]> pd.if.org Git - pdclib/commitdiff
Added setvbuf().
authorsolar <unknown>
Fri, 9 Jun 2006 05:52:38 +0000 (05:52 +0000)
committersolar <unknown>
Fri, 9 Jun 2006 05:52:38 +0000 (05:52 +0000)
functions/stdio/fopen.c
functions/stdio/setvbuf.c
includes/stdio.h
internals/_PDCLIB_int.h

index 1e9bd41358a60aa48484325bf9afe7333a4663e9..9a01fe3debc8f225a5bdd1244ba85814355589f1 100644 (file)
@@ -77,13 +77,12 @@ struct _PDCLIB_file_t * fopen( const char * _PDCLIB_restrict filename, const cha
     if ( ( rc->status = filemode( mode ) ) == 0 ) goto fail; /* invalid mode */
     rc->handle = _PDCLIB_open( filename, rc->status );
     if ( rc->handle == _PDCLIB_NOHANDLE ) goto fail; /* OS open() failed */
-
     /* Adding to list of open files */
     rc->next = _PDCLIB_filelist;
     _PDCLIB_filelist = rc;
     /* Setting buffer, and mark as internal. TODO: Check for unbuffered? */
     if ( ( rc->buffer = malloc( BUFSIZ ) ) == NULL ) goto fail;
-    rc->status |= _PDCLIB_LIBBUFFER;
+    rc->status |= ( _PDCLIB_LIBBUFFER | _PDCLIB_VIRGINSTR );
     /* TODO: Setting mbstate */
     return rc;
 fail:
index 9d96ad8f8583e3681e8bdfa8d162c613a6231cab..c6329df9b6f07fe823a2570e3d0b3533f6fca49a 100644 (file)
 
 #ifndef REGTEST
 
-int setvbuf( FILE * _PDCLIB_restrict stream, char * _PDCLIB_restrict buf, int mode, size_t size )
+int setvbuf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, char * _PDCLIB_restrict buf, int mode, size_t size )
 {
-    /* TODO: Only allowed on a "virgin" stream; add check. */
-    if ( ( stream->status & ( _IOFBF | _IOLBF | _IONBF ) ) /* Only allowed on "virgin" stream */
-      || ( ( mode != _IOFBF ) && ( mode != _IOLBF ) && ( mode != _IONBF ) ) /* invalid mode */
-      || ( ( buf == NULL ) && ( ( buf = malloc( size ) ) == NULL ) ) /* no memory available */
-    )
+    /* Only allowed on "virgin" streams (i.e., before first I/O occurs), and
+       a valid value for mode.
+    */
+    if ( ( ! stream->status & _PDCLIB_VIRGINSTR ) ||
+         ( ( mode != _IOFBF ) && ( mode != _IOLBF ) && ( mode != _IONBF ) ) )
     {
         return -1;
     }
+    /* If a buffer is provided by user... */
+    if ( buf != NULL )
+    {
+        /* ...do not free it in library functions like fclose(), freopen(). */
+        stream->status &= ~_PDCLIB_LIBBUFFER;
+    }
+    /* If no buffer is provided by user, but required... */
+    else if ( mode != _IONBF )
+    {
+        /* Since setvbuf() may be called (successfully) on a stream only once,
+           the stream's buffer at this point should *always* be that allocated
+           by fopen(), but better make sure.
+        */
+        if ( ! ( stream->status & _PDCLIB_LIBBUFFER ) )
+        {
+            return -1;
+        }
+        /* Drop old buffer, allocate new one of requested size (unless that is
+           equal to BUFSIZ, in which case we can use the one already allocated
+           by fopen().)
+        */
+        if ( size != BUFSIZ )
+        {
+            if ( ( buf = malloc( size ) ) == NULL )
+            {
+                return -1;
+            }
+            free( stream->buffer );
+        }
+    }
+    /* Applying new settings to stream. */
+    stream->status &= ~( _IOFBF | _IOLBF | _IONBF );
     stream->status |= mode;
-    stream->buffer  = buf;
+    stream->buffer = buf;
     stream->bufsize = size;
+    stream->status &= ~_PDCLIB_VIRGINSTR;
     return 0;
 }
 
@@ -34,7 +67,11 @@ int setvbuf( FILE * _PDCLIB_restrict stream, char * _PDCLIB_restrict buf, int mo
 
 int main( void )
 {
+#ifndef REGTEST
     TESTCASE( NO_TESTDRIVER );
+#else
+    puts( " NOTEST setvbuf() test driver is PDCLib-specific." );
+#endif
     return TEST_RESULTS;
 }
 
index e4b16733375e44cebc4a30c5b97ab6015442353e..02d711e4ef0e26448c1b23a2ee5ba7b3d37bcd02 100644 (file)
@@ -25,9 +25,9 @@ typedef _PDCLIB_size_t size_t;
 #endif
 
 /* See setvbuf(), third argument */
-#define _IOFBF 2
-#define _IOLBF 1
-#define _IONBF 0
+#define _IOFBF 1
+#define _IOLBF 2
+#define _IONBF 4
 
 /* The following are platform-dependant, and defined in _PDCLIB_config.h. */
 typedef _PDCLIB_fpos_t        fpos_t;
index a0a63704f889bc033c2b8aee4b2d8ce672f1ac0c..7c061c8b3ff790b0890288436def74a50c1117c3 100644 (file)
@@ -254,16 +254,19 @@ typedef unsigned _PDCLIB_intmax _PDCLIB_uintmax_t;
 /* Various <stdio.h> internals                                                */
 /* -------------------------------------------------------------------------- */
 
-/* Flags for representing mode (see fopen()). */
-#define _PDCLIB_FREAD    1u
-#define _PDCLIB_FWRITE   2u
-#define _PDCLIB_FAPPEND  4u 
-#define _PDCLIB_FRW      8u
-#define _PDCLIB_FBIN    16u
+/* Flags for representing mode (see fopen()). Note these must fit the same
+   status field as the _IO?BF flags in <stdio.h> and the internal flags below.
+*/
+#define _PDCLIB_FREAD    8u
+#define _PDCLIB_FWRITE   16u
+#define _PDCLIB_FAPPEND  32u 
+#define _PDCLIB_FRW      64u
+#define _PDCLIB_FBIN    128u
 
 /* Internal flags, made to fit the same status field as the flags above. */
-#define _PDCLIB_WROTELAST 32u
-#define _PDCLIB_LIBBUFFER 64u
+#define _PDCLIB_WROTELAST  256u
+#define _PDCLIB_LIBBUFFER  512u
+#define _PDCLIB_VIRGINSTR 1024u
 
 struct _PDCLIB_file_t
 {