X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=functions%2Fstdio%2Ffreopen.c;h=482b82025d225cf5d5cdbb2b1e9a2e0000177ba0;hb=71712a8bb92d6a10218e3356c6d26554dc2633dd;hp=13992deb8214f5fe9f7e7d76584da4a5b1247dc3;hpb=f2dbc6a41d71a685ce2a69e83eaa5172fff5066a;p=pdclib diff --git a/functions/stdio/freopen.c b/functions/stdio/freopen.c index 13992de..482b820 100644 --- a/functions/stdio/freopen.c +++ b/functions/stdio/freopen.c @@ -1,6 +1,6 @@ /* $Id$ */ -/* freopen( const char *, const char * ) +/* freopen( const char *, const char *, FILE * ) This file is part of the Public Domain C Library (PDCLib). Permission is granted to use, modify, and / or redistribute at will. @@ -12,33 +12,65 @@ #include <_PDCLIB_glue.h> #include +#include -/* Close any file currently associated with the given stream. Open the file - identified by the given filename with the given mode (equivalent to fopen()), - and associate it with the given stream. If filename is a NULL pointer, - attempt to change the mode of the given stream. - This implementation allows the following mode changes: TODO - (Primary use of this function is to redirect stdin, stdout, and stderr.) -*/ - -struct _PDCLIB_file_t * freopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, struct _PDCLIB_file_t * stream ) +struct _PDCLIB_file_t * freopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) { - /* FIXME: This is ad-hoc (to make the vprintf() testdriver work), and must be checked. */ - /* FIXME: If filename is NULL, change mode. */ + unsigned int status = stream->status & ( _IONBF | _IOLBF | _IOFBF | _PDCLIB_FREEBUFFER | _PDCLIB_DELONCLOSE ); /* TODO: This function can change wide orientation of a stream */ - if ( filename == NULL ) return NULL; - if ( stream->status & _PDCLIB_WROTELAST ) fflush( stream ); - if ( stream->status & _PDCLIB_LIBBUFFER ) free( stream->buffer ); + if ( stream->status & _PDCLIB_FWRITE ) + { + _PDCLIB_flushbuffer( stream ); + } + if ( ( filename == NULL ) && ( stream->filename == NULL ) ) + { + /* TODO: Special handling for mode changes on std-streams */ + return NULL; + } _PDCLIB_close( stream->handle ); + /* TODO: It is not nice to do this on a stream we just closed. + It does not matter with the current implementation of clearerr(), + but it might start to matter if someone replaced that implementation. + */ clearerr( stream ); - if ( ( mode == NULL ) || ( filename[0] == '\0' ) ) return NULL; - if ( ( stream->status = _PDCLIB_filemode( mode ) ) == 0 ) return NULL; - stream->handle = _PDCLIB_open( filename, stream->status ); - if ( ( stream->buffer = malloc( BUFSIZ ) ) == NULL ) return NULL; - stream->bufsize = BUFSIZ; + /* The new filename might not fit the old buffer */ + if ( filename == NULL ) + { + /* Use previous filename */ + filename = stream->filename; + } + else if ( ( stream->filename != NULL ) && ( strlen( stream->filename ) >= strlen( filename ) ) ) + { + /* Copy new filename into existing buffer */ + strcpy( stream->filename, filename ); + } + else + { + /* Allocate new buffer */ + if ( ( stream->filename = (char *)malloc( strlen( filename ) ) ) == NULL ) + { + return NULL; + } + strcpy( stream->filename, filename ); + } + if ( ( mode == NULL ) || ( filename[0] == '\0' ) ) + { + return NULL; + } + if ( ( stream->status = _PDCLIB_filemode( mode ) ) == 0 ) + { + return NULL; + } + /* Re-add the flags we saved above */ + stream->status |= status; stream->bufidx = 0; - stream->status |= ( _PDCLIB_LIBBUFFER | _PDCLIB_VIRGINSTR ); + stream->bufend = 0; + stream->ungetidx = 0; /* TODO: Setting mbstate */ + if ( ( stream->handle = _PDCLIB_open( filename, stream->status ) ) == _PDCLIB_NOHANDLE ) + { + return NULL; + } return stream; }