From: solar Date: Fri, 9 Jun 2006 05:52:38 +0000 (+0000) Subject: Added setvbuf(). X-Git-Tag: v0.5~163 X-Git-Url: https://pd.if.org/git/?p=pdclib;a=commitdiff_plain;h=90e52eb83afae4969bec36cd11ece85507458f79 Added setvbuf(). --- diff --git a/functions/stdio/fopen.c b/functions/stdio/fopen.c index 1e9bd41..9a01fe3 100644 --- a/functions/stdio/fopen.c +++ b/functions/stdio/fopen.c @@ -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: 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; } diff --git a/includes/stdio.h b/includes/stdio.h index e4b1673..02d711e 100644 --- a/includes/stdio.h +++ b/includes/stdio.h @@ -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; diff --git a/internals/_PDCLIB_int.h b/internals/_PDCLIB_int.h index a0a6370..7c061c8 100644 --- a/internals/_PDCLIB_int.h +++ b/internals/_PDCLIB_int.h @@ -254,16 +254,19 @@ typedef unsigned _PDCLIB_intmax _PDCLIB_uintmax_t; /* Various 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 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 {