X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=functions%2Fstdio%2Fsetvbuf.c;fp=functions%2Fstdio%2Fsetvbuf.c;h=c6329df9b6f07fe823a2570e3d0b3533f6fca49a;hb=90e52eb83afae4969bec36cd11ece85507458f79;hp=9d96ad8f8583e3681e8bdfa8d162c613a6231cab;hpb=188eee8e94ce6e968e0791bae1c7682dafe9ec9c;p=pdclib diff --git a/functions/stdio/setvbuf.c b/functions/stdio/setvbuf.c index 9d96ad8..c6329df 100644 --- a/functions/stdio/setvbuf.c +++ b/functions/stdio/setvbuf.c @@ -11,19 +11,52 @@ #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; }