buffered if and only if it can be determined not to refer to an
interactive device."
*/
- rc->status |= _PDCLIB_LIBBUFFER | _IOLBF;
+ rc->status |= _IOLBF;
/* TODO: Setting mbstate */
/* Adding to list of open files */
rc->next = _PDCLIB_filelist;
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
+ This implementation allows any mode changes.
(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 * _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_FWRITE ) fflush( stream );
- if ( stream->status & _PDCLIB_LIBBUFFER ) free( stream->buffer );
+ if ( stream->status & _PDCLIB_FWRITE )
+ {
+ _PDCLIB_flushbuffer( stream );
+ }
_PDCLIB_close( stream->handle );
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;
+ /* FIXME: Copy filename into the FILE structure. */
+ /* FIXME: filename cannot reside in "big block" memory */
+ if ( filename == NULL )
+ {
+ filename = stream->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;
+ stream->bufend = 0;
+ stream->ungetidx = 0;
/* TODO: Setting mbstate */
+ if ( ( stream->handle = _PDCLIB_open( filename, stream->status ) ) == _PDCLIB_NOHANDLE )
+ {
+ return NULL;
+ }
return stream;
}
we don't want to e.g. flush the stream for every character of a
stream being printed.
*/
+ /* TODO: Check this */
break;
case _IOFBF:
case _IOLBF:
- if ( size > INT_MAX || size == NULL )
+ if ( size > INT_MAX || size == 0 )
{
/* PDCLib only supports buffers up to INT_MAX in size. A size
of zero doesn't make sense.
/* User requested buffer size, but leaves it to library to
allocate the buffer.
*/
+ /* If current buffer is big enough for requested size, but not
+ over twice as big (and wasting memory space), we use the
+ current buffer (i.e., do nothing), to save the malloc() /
+ free() overhead.
+ */
if ( ( stream->bufsize < size ) || ( stream->bufsize > ( size << 1 ) ) )
{
- /* If current buffer is big enough for requested size, but
- not over twice as big (and wasting memory space), we use
- the current buffer (i.e., do nothing), to save the
- malloc() / free() overhead.
- */
- /* Free the buffer allocated by fopen(), and allocate a new
- one.
- */
+ /* Buffer too small, or much too large - allocate. */
if ( ( buf = (char *) malloc( size ) ) == NULL )
{
/* Out of memory error. */
return -1;
}
+ /* This buffer must be free()d on fclose() */
+ stream->status |= _PDCLIB_FREEBUFFER;
}
}
- else
- {
- /* User provided buffer -> set flag to not free() the buffer
- on fclose().
- */
- stream->status &= ~ _PDCLIB_LIBBUFFER;
- }
- free( stream->buffer );
stream->buffer = buf;
stream->bufsize = size;
break;
#define _PDCLIB_FBIN 128u
/* Internal flags, made to fit the same status field as the flags above. */
-#define _PDCLIB_LIBBUFFER 512u
+#define _PDCLIB_FREEBUFFER 512u
#define _PDCLIB_ERRORFLAG 1024u
#define _PDCLIB_EOFFLAG 2048u
#define _PDCLIB_WIDESTREAM 4096u
here.
*/
int osmode;
- switch ( mode & ~_PDCLIB_FBIN )
+ switch ( mode & ( _PDCLIB_FREAD | _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_FRW ) )
{
case _PDCLIB_FREAD: /* "r" */
osmode = O_RDONLY;
here.
*/
int osmode;
- switch ( mode & ~_PDCLIB_FBIN )
+ switch ( mode & ( _PDCLIB_FREAD | _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_FRW ) )
{
case _PDCLIB_FREAD: /* "r" */
osmode = O_RDONLY;