From c5d49235e09fbd58416f10dec2799e61cf3431c8 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Wed, 5 Dec 2012 02:20:16 +0000 Subject: [PATCH] PDCLIB-8: First phase of intergation of new I/O backend system (with minimal disruption of existing code) * _PDCLIB_fdopen: renamed _PDCLIB_fvopen to more clearly deliniate from POSIX fdopen function and state purpose * _PDCLIB_fd_t is now a library provided union type Contains members of type void*, uintptr_t, intptr_t. If another type is required, define _PDCLIB_OSFD_T to that type in _PDCLIB_config.h * _PDCLIB_fileops_t added. This structure contains the file operations * _PDCLIB_fillbuffer, _PDCLIB_flushbuffer, _PDCLIB_seek become internal APIs (_PDCLIB_seek's days are numbered!) * _PDCLIB_close is removed * tmpfile() and fopen() should now call through to _PDCLIB_fvopen and provide a pointer to an appropriate _PDCLIB_fileops_t structure Win32 port updated. Other ports are TODO --- .../stdio}/_PDCLIB_fillbuffer.c | 99 +++++++------- .../stdio}/_PDCLIB_flushbuffer.c | 122 ++++++++---------- .../{_PDCLIB_fdopen.c => _PDCLIB_fvopen.c} | 6 +- functions/stdio/_PDCLIB_seek.c | 39 ++++++ functions/stdio/fclose.c | 2 +- functions/stdio/fopen.c | 9 +- functions/stdio/freopen.c | 6 +- includes/stdio.h | 6 +- internals/_PDCLIB_aux.h | 6 +- internals/_PDCLIB_glue.h | 36 ++---- internals/_PDCLIB_io.h | 120 +++++++++++++++-- platform/win32/crt0.c | 6 +- .../win32/functions/_PDCLIB/_PDCLIB_close.c | 39 ------ .../win32/functions/_PDCLIB/_PDCLIB_fileops.c | 87 +++++++++++++ .../win32/functions/_PDCLIB/_PDCLIB_open.c | 15 ++- .../win32/functions/_PDCLIB/_PDCLIB_seek.c | 51 -------- .../win32/functions/_PDCLIB/_PDCLIB_stdinit.c | 8 +- platform/win32/functions/stdio/tmpfile.c | 4 +- platform/win32/internals/_PDCLIB_config.h | 3 - 19 files changed, 385 insertions(+), 279 deletions(-) rename {platform/win32/functions/_PDCLIB => functions/stdio}/_PDCLIB_fillbuffer.c (62%) rename {platform/win32/functions/_PDCLIB => functions/stdio}/_PDCLIB_flushbuffer.c (70%) rename functions/stdio/{_PDCLIB_fdopen.c => _PDCLIB_fvopen.c} (90%) create mode 100644 functions/stdio/_PDCLIB_seek.c delete mode 100644 platform/win32/functions/_PDCLIB/_PDCLIB_close.c create mode 100644 platform/win32/functions/_PDCLIB/_PDCLIB_fileops.c delete mode 100644 platform/win32/functions/_PDCLIB/_PDCLIB_seek.c diff --git a/platform/win32/functions/_PDCLIB/_PDCLIB_fillbuffer.c b/functions/stdio/_PDCLIB_fillbuffer.c similarity index 62% rename from platform/win32/functions/_PDCLIB/_PDCLIB_fillbuffer.c rename to functions/stdio/_PDCLIB_fillbuffer.c index c6a2b6b..dfdfe26 100644 --- a/platform/win32/functions/_PDCLIB/_PDCLIB_fillbuffer.c +++ b/functions/stdio/_PDCLIB_fillbuffer.c @@ -1,54 +1,45 @@ -/* $Id$ */ - -/* _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is a stub version of _PDCLIB_fillbuffer -*/ - -#include - -#ifndef REGTEST -#include <_PDCLIB_glue.h> -#include -#include - -void _PDCLIB_w32errno(void); -int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ) -{ - DWORD nBytesRead; - BOOL ok = ReadFile( stream->handle, stream->buffer, stream->bufsize, - &nBytesRead, NULL ); - - if( ok ) { - if( nBytesRead == 0 ) { - stream->status |= _PDCLIB_EOFFLAG; - return EOF; - } - stream->pos.offset += nBytesRead; - stream->bufend = nBytesRead; - stream->bufidx = 0; - return 0; - } else { - _PDCLIB_w32errno(); - stream->status |= _PDCLIB_ERRORFLAG; - return EOF; - } -} - -#endif - -#ifdef TEST -#include <_PDCLIB_test.h> - -int main( void ) -{ - /* Testing covered by ftell.c */ - return TEST_RESULTS; -} - -#endif - +/* _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST +#include <_PDCLIB_glue.h> + +int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ) +{ + size_t bytesRead; + bool ok = stream->ops->read( stream->handle, stream->buffer, stream->bufsize, + &bytesRead); + + if( ok ) { + if( bytesRead == 0 ) { + stream->status |= _PDCLIB_EOFFLAG; + return EOF; + } + stream->pos.offset += bytesRead; + stream->bufend = bytesRead; + stream->bufidx = 0; + return 0; + } else { + stream->status |= _PDCLIB_ERRORFLAG; + return EOF; + } +} + +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif + diff --git a/platform/win32/functions/_PDCLIB/_PDCLIB_flushbuffer.c b/functions/stdio/_PDCLIB_flushbuffer.c similarity index 70% rename from platform/win32/functions/_PDCLIB/_PDCLIB_flushbuffer.c rename to functions/stdio/_PDCLIB_flushbuffer.c index c0ade01..ffbbb4f 100644 --- a/platform/win32/functions/_PDCLIB/_PDCLIB_flushbuffer.c +++ b/functions/stdio/_PDCLIB_flushbuffer.c @@ -1,66 +1,56 @@ -/* $Id$ */ - -/* _PDCLIB_flushbuffer( struct _PDCLIB_file_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is a stub implementation of _PDCLIB_flushbuffer -*/ - -#include -#include - -#ifndef REGTEST -#include <_PDCLIB_glue.h> -#include -#include - -void _PDCLIB_w32errno( void ); - -int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream ) -{ - if ( ! ( stream->status & _PDCLIB_FBIN ) ) - { - /* TODO: Text stream conversion here */ - } - - DWORD written = 0; - - - while(written != stream->bufidx) { - DWORD justWrote; - DWORD toWrite = stream->bufidx - written; - BOOL res = WriteFile( stream->handle, stream->buffer + written, - toWrite, &justWrote, NULL); - written += justWrote; - stream->pos.offset += justWrote; - - if(!res) { - stream->status |=_PDCLIB_ERRORFLAG; - stream->bufidx -= written; - memmove( stream->buffer, stream->buffer + written, stream->bufidx ); - _PDCLIB_w32errno(); - return EOF; - } - } - - stream->bufidx = 0; - return 0; -} - -#endif - - -#ifdef TEST -#include <_PDCLIB_test.h> - -int main( void ) -{ - /* Testing covered by ftell.c */ - return TEST_RESULTS; -} - -#endif - +/* _PDCLIB_flushbuffer( struct _PDCLIB_file_t * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include +#include + +#ifndef REGTEST +#include <_PDCLIB_glue.h> + +int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream ) +{ + if ( ! ( stream->status & _PDCLIB_FBIN ) ) + { + /* TODO: Text stream conversion here */ + } + + size_t written = 0; + + + while(written != stream->bufidx) { + size_t justWrote; + size_t toWrite = stream->bufidx - written; + bool res = stream->ops->write( stream->handle, stream->buffer + written, + toWrite, &justWrote); + written += justWrote; + stream->pos.offset += justWrote; + + if(!res) { + stream->status |=_PDCLIB_ERRORFLAG; + stream->bufidx -= written; + memmove( stream->buffer, stream->buffer + written, stream->bufidx ); + return EOF; + } + } + + stream->bufidx = 0; + return 0; +} + +#endif + + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif + diff --git a/functions/stdio/_PDCLIB_fdopen.c b/functions/stdio/_PDCLIB_fvopen.c similarity index 90% rename from functions/stdio/_PDCLIB_fdopen.c rename to functions/stdio/_PDCLIB_fvopen.c index c628ebc..466009b 100644 --- a/functions/stdio/_PDCLIB_fdopen.c +++ b/functions/stdio/_PDCLIB_fvopen.c @@ -1,6 +1,6 @@ /* $Id$ */ -/* _PDCLIB_fdopen( _PDCLIB_fd_t fd, const char * ) +/* _PDCLIB_fvopen( _PDCLIB_fd_t fd, _PDCLIB_fileops_t * ) This file is part of the Public Domain C Library (PDCLib). Permission is granted to use, modify, and / or redistribute at will. @@ -16,7 +16,8 @@ extern struct _PDCLIB_file_t * _PDCLIB_filelist; -struct _PDCLIB_file_t * _PDCLIB_fdopen( _PDCLIB_fd_t fd, +struct _PDCLIB_file_t * _PDCLIB_fvopen( _PDCLIB_fd_t fd, + const _PDCLIB_fileops_t * ops, int mode, const char * _PDCLIB_restrict filename ) { @@ -47,6 +48,7 @@ struct _PDCLIB_file_t * _PDCLIB_fdopen( _PDCLIB_fd_t fd, } rc->status = mode; + rc->ops = ops; rc->handle = fd; /* Setting pointers into the memory block allocated above */ rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t ); diff --git a/functions/stdio/_PDCLIB_seek.c b/functions/stdio/_PDCLIB_seek.c new file mode 100644 index 0000000..5a3f982 --- /dev/null +++ b/functions/stdio/_PDCLIB_seek.c @@ -0,0 +1,39 @@ +/* int64_t _PDCLIB_seek( FILE *, int64_t, int ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include +#include +#include +#ifndef REGTEST + +int_fast64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int64_t offset, + int whence ) +{ + int_fast64_t newPos; + if(!stream->ops->seek(stream->handle, offset, whence, &newPos)) { + return EOF; + } + + stream->ungetidx = 0; + stream->bufidx = 0; + stream->bufend = 0; + stream->pos.offset = newPos; + return newPos; +} + +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + /* Testing covered by ftell.c */ + return TEST_RESULTS; +} + +#endif + diff --git a/functions/stdio/fclose.c b/functions/stdio/fclose.c index c4f5d8a..3d9e257 100644 --- a/functions/stdio/fclose.c +++ b/functions/stdio/fclose.c @@ -39,7 +39,7 @@ int fclose( struct _PDCLIB_file_t * stream ) mtx_destroy( &stream->lock ); /* Close handle */ - _PDCLIB_close( stream->handle ); + stream->ops->close(stream->handle); /* Remove stream from list */ if ( previous != NULL ) diff --git a/functions/stdio/fopen.c b/functions/stdio/fopen.c index ff8e8e8..e806b00 100644 --- a/functions/stdio/fopen.c +++ b/functions/stdio/fopen.c @@ -24,15 +24,16 @@ FILE * fopen( const char * _PDCLIB_restrict filename, if( imode == 0 || filename == NULL ) return NULL; - _PDCLIB_fd_t fd = _PDCLIB_open( filename, imode ); - if(fd == _PDCLIB_NOHANDLE) { + _PDCLIB_fd_t fd; + const _PDCLIB_fileops_t * ops; + if(!_PDCLIB_open( &fd, &ops, filename, imode )) { return NULL; } - FILE * f = _PDCLIB_fdopen( fd, imode, filename ); + FILE * f = _PDCLIB_fvopen( fd, ops, imode, filename ); if(!f) { int saveErrno = errno; - _PDCLIB_close( fd ); + ops->close(fd); errno = saveErrno; } return f; diff --git a/functions/stdio/freopen.c b/functions/stdio/freopen.c index 7868c95..9c49756 100644 --- a/functions/stdio/freopen.c +++ b/functions/stdio/freopen.c @@ -33,7 +33,8 @@ struct _PDCLIB_file_t * freopen( funlockfile( stream ); return NULL; } - _PDCLIB_close( stream->handle ); + stream->ops->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. @@ -76,7 +77,8 @@ struct _PDCLIB_file_t * freopen( stream->bufend = 0; stream->ungetidx = 0; /* TODO: Setting mbstate */ - if ( ( stream->handle = _PDCLIB_open( filename, stream->status ) ) == _PDCLIB_NOHANDLE ) + if ( ! _PDCLIB_open( &stream->handle, &stream->ops, filename, + stream->status ) ) { funlockfile( stream ); return NULL; diff --git a/includes/stdio.h b/includes/stdio.h index 79a54bd..9d423c1 100644 --- a/includes/stdio.h +++ b/includes/stdio.h @@ -171,12 +171,14 @@ int fflush( FILE * stream ) _PDCLIB_nothrow; Returns a pointer to the stream handle if successfull, NULL otherwise. */ -FILE * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode ) _PDCLIB_nothrow; +FILE * fopen( const char * _PDCLIB_restrict filename, + const char * _PDCLIB_restrict mode ) _PDCLIB_nothrow; /* Creates a stream connected to the file descriptor \p fd with mode \p mode. Mode must match the mode with which the file descriptor was opened. */ -FILE * _PDCLIB_fdopen( _PDCLIB_fd_t fd, int mode, const char* filename ) _PDCLIB_nothrow; +FILE * _PDCLIB_fvopen( _PDCLIB_fd_t fd, const _PDCLIB_fileops_t * ops, + int mode, const char * filename ) _PDCLIB_nothrow; /* Close any file currently associated with the given stream. Open the file identified by the given filename with the given mode (equivalent to fopen()), diff --git a/internals/_PDCLIB_aux.h b/internals/_PDCLIB_aux.h index bfb0842..0844962 100644 --- a/internals/_PDCLIB_aux.h +++ b/internals/_PDCLIB_aux.h @@ -160,9 +160,11 @@ #ifdef __cplusplus #define _PDCLIB_BEGIN_EXTERN_C extern "C" { #define _PDCLIB_END_EXTERN_C } + typedef bool _PDCLIB_bool; #else - #define _PDCLIB_BEGIN_EXTERN_C - #define _PDCLIB_END_EXTERN_C + #define _PDCLIB_BEGIN_EXTERN_C + #define _PDCLIB_END_EXTERN_C + typedef _Bool _PDCLIB_bool; #endif /*#if _PDCLIB_C_VERSION != 1999 diff --git a/internals/_PDCLIB_glue.h b/internals/_PDCLIB_glue.h index d49cc11..7f3c4fa 100644 --- a/internals/_PDCLIB_glue.h +++ b/internals/_PDCLIB_glue.h @@ -9,6 +9,7 @@ */ #include <_PDCLIB_int.h> +#include <_PDCLIB_io.h> #include #include _PDCLIB_BEGIN_EXTERN_C @@ -49,33 +50,14 @@ void * _PDCLIB_reallocpages( void* p, size_t on, size_t nn, bool mayMove); /* stdio.h */ -/* A system call that opens a file identified by name in a given mode. Return - a file descriptor uniquely identifying that file. - (The mode is the return value of the _PDCLIB_filemode() function.) -*/ -_PDCLIB_fd_t _PDCLIB_open( char const * const filename, unsigned int mode ); - -/* A system call that writes a stream's buffer. - Returns 0 on success, EOF on write error. - Sets stream error flags and errno appropriately on error. -*/ -int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream ); - -/* A system call that fills a stream's buffer. - Returns 0 on success, EOF on read error / EOF. - Sets stream EOF / error flags and errno appropriately on error. -*/ -int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ); - -/* A system call that repositions within a file. Returns new offset on success, - -1 / errno on error. -*/ -_PDCLIB_int64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int64_t offset, int whence ); - -/* A system call that closes a file identified by given file descriptor. Return - zero on success, non-zero otherwise. -*/ -int _PDCLIB_close( _PDCLIB_fd_t fd ); +/* Open the file with the given name and mode. Return the file descriptor in + * *fd and a pointer to the operations structure in **ops on success. + * + * Return true on success and false on failure. + */ +bool _PDCLIB_open( + _PDCLIB_fd_t* fd, const _PDCLIB_fileops_t** ops, + char const * filename, unsigned int mode ); /* A system call that removes a file identified by name. Return zero on success, non-zero otherwise. diff --git a/internals/_PDCLIB_io.h b/internals/_PDCLIB_io.h index 0dfdad2..829bb45 100644 --- a/internals/_PDCLIB_io.h +++ b/internals/_PDCLIB_io.h @@ -34,29 +34,121 @@ /* stream handle should not be free()d on close (stdin, stdout, stderr) */ #define _PDCLIB_STATIC 32768u +typedef union _PDCLIB_fd +{ +#if defined(_PDCLIB_OSFD_T) + _PDCLIB_OSFD_T osfd; +#endif + void * pointer; + _PDCLIB_uintptr_t uval; + _PDCLIB_intptr_t sval; +} _PDCLIB_fd_t; + +/* Internal functions */ +/* Writes a stream's buffer. + Returns 0 on success, EOF on write error. + Sets stream error flags and errno appropriately on error. +*/ +int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream ); + +/* Fills a stream's buffer. + Returns 0 on success, EOF on read error / EOF. + Sets stream EOF / error flags and errno appropriately on error. +*/ +int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ); + +/* Repositions within a file. Returns new offset on success, + -1 / errno on error. +*/ +_PDCLIB_int_fast64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, + _PDCLIB_int_fast64_t offset, int whence ); + +/* File backend I/O operations + * + * PDCLib will call through to these methods as needed to implement the stdio + * functions. + */ +typedef struct _PDCLIB_fileops +{ + /*! Read length bytes from the file into buf; returning the number of bytes + * actually read in *numBytesRead. + * + * Returns true if bytes were read successfully; on end of file, returns + * true with *numBytesRead == 0. + * + * On error, returns false and sets errno appropriately. *numBytesRead is + * ignored in this situation. + */ + _PDCLIB_bool (*read)( _PDCLIB_fd_t self, + void * buf, + _PDCLIB_size_t length, + _PDCLIB_size_t * numBytesRead ); + + /*! Write length bytes to the file from buf; returning the number of bytes + * actually written in *numBytesWritten + * + * Returns true if bytes were written successfully. On error, returns false + * and setss errno appropriately (as with read, *numBytesWritten is + * ignored) + */ + _PDCLIB_bool (*write)( _PDCLIB_fd_t self, const void * buf, + _PDCLIB_size_t length, _PDCLIB_size_t * numBytesWritten ); + + /* Seek to the file offset specified by offset, from location whence, which + * may be one of the standard constants SEEK_SET/SEEK_CUR/SEEK_END + */ + _PDCLIB_bool (*seek)( _PDCLIB_fd_t self, _PDCLIB_int_fast64_t offset, + int whence, _PDCLIB_int_fast64_t *newPos ); + + void (*close)( _PDCLIB_fd_t self ); + + /*! Behaves as read does, except for wide characters. Both length and + * *numCharsRead represent counts of characters, not bytes. + * + * This function is optional; if missing, PDCLib will buffer the character + * data as bytes and perform translation directly into the user's buffers. + * It is useful if your backend can directly take wide characters (for + * example, the Windows console) + */ + _PDCLIB_bool (*wread)( _PDCLIB_fd_t self, _PDCLIB_wchar_t * buf, + _PDCLIB_size_t length, _PDCLIB_size_t * numCharsRead ); + + /* Behaves as write does, except for wide characters. As with wread, both + * length and *numCharsWritten are character counts. + * + * This function is also optional; if missing, PDCLib will buffer the + * character data as bytes and do translation directly from the user's + * buffers. You only need to implement this if your backend can directly + * take wide characters (for example, the Windows console) + */ + _PDCLIB_bool (*wwrite)( _PDCLIB_fd_t self, const _PDCLIB_wchar_t * buf, + _PDCLIB_size_t length, _PDCLIB_size_t * numCharsWritten ); +} _PDCLIB_fileops_t; + /* Position / status structure for getpos() / fsetpos(). */ struct _PDCLIB_fpos_t { - _PDCLIB_uint64_t offset; /* File position offset */ - int status; /* Multibyte parsing state (unused, reserved) */ + _PDCLIB_int_fast64_t offset; /* File position offset */ + int status; /* Multibyte parsing state (unused, reserved) */ }; /* FILE structure */ struct _PDCLIB_file_t { - _PDCLIB_fd_t handle; /* OS file handle */ - _PDCLIB_MTX_T lock; /* file lock */ - char * buffer; /* Pointer to buffer memory */ - _PDCLIB_size_t bufsize; /* Size of buffer */ - _PDCLIB_size_t bufidx; /* Index of current position in buffer */ - _PDCLIB_size_t bufend; /* Index of last pre-read character in buffer */ - struct _PDCLIB_fpos_t pos; /* Offset and multibyte parsing state */ - _PDCLIB_size_t ungetidx; /* Number of ungetc()'ed characters */ - unsigned char * ungetbuf; /* ungetc() buffer */ - unsigned int status; /* Status flags; see above */ + const _PDCLIB_fileops_t * ops; + _PDCLIB_fd_t handle; /* OS file handle */ + _PDCLIB_MTX_T lock; /* file lock */ + char * buffer; /* Pointer to buffer memory */ + _PDCLIB_size_t bufsize; /* Size of buffer */ + _PDCLIB_size_t bufidx; /* Index of current position in buffer */ + _PDCLIB_size_t bufend; /* Index of last pre-read character in buffer */ + struct _PDCLIB_fpos_t pos; /* Offset and multibyte parsing state */ + _PDCLIB_size_t ungetidx; /* Number of ungetc()'ed characters */ + unsigned char * ungetbuf; /* ungetc() buffer */ + unsigned int status; /* Status flags; see above */ /* multibyte parsing status to be added later */ - char * filename; /* Name the current stream has been opened with */ - struct _PDCLIB_file_t * next; /* Pointer to next struct (internal) */ + char * filename; /* Name the current stream has been opened with */ + struct _PDCLIB_file_t * next; /* Pointer to next struct (internal) */ }; diff --git a/platform/win32/crt0.c b/platform/win32/crt0.c index 7da2a81..d32a6ac 100644 --- a/platform/win32/crt0.c +++ b/platform/win32/crt0.c @@ -104,9 +104,9 @@ void __cdecl mainCRTStartup( void ); void __cdecl mainCRTStartup( void ) { - stdin->handle = GetStdHandle(STD_INPUT_HANDLE); - stdout->handle = GetStdHandle(STD_OUTPUT_HANDLE); - stderr->handle = GetStdHandle(STD_ERROR_HANDLE); + stdin->handle.pointer = GetStdHandle(STD_INPUT_HANDLE); + stdout->handle.pointer = GetStdHandle(STD_OUTPUT_HANDLE); + stderr->handle.pointer = GetStdHandle(STD_ERROR_HANDLE); oldFilter = SetUnhandledExceptionFilter( sehExceptionFilter ); diff --git a/platform/win32/functions/_PDCLIB/_PDCLIB_close.c b/platform/win32/functions/_PDCLIB/_PDCLIB_close.c deleted file mode 100644 index 7fc10a3..0000000 --- a/platform/win32/functions/_PDCLIB/_PDCLIB_close.c +++ /dev/null @@ -1,39 +0,0 @@ -/* $Id$ */ - -/* _PDCLIB_close( _PDCLIB_fd_t fd ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is a stub example implementation of _PDCLIB_close() -*/ - -#include - -#ifndef REGTEST -#include <_PDCLIB_glue.h> -#include -#include - -void _PDCLIB_w32errno(void); -int _PDCLIB_close( HANDLE fd ) -{ - if(CloseHandle((HANDLE) fd)) - return 0; - _PDCLIB_w32errno(); - return 1; -} - -#endif - -#ifdef TEST -#include <_PDCLIB_test.h> - -int main( void ) -{ - /* No testdriver; tested in driver for _PDCLIB_open(). */ - return TEST_RESULTS; -} - -#endif diff --git a/platform/win32/functions/_PDCLIB/_PDCLIB_fileops.c b/platform/win32/functions/_PDCLIB/_PDCLIB_fileops.c new file mode 100644 index 0000000..1d48e11 --- /dev/null +++ b/platform/win32/functions/_PDCLIB/_PDCLIB_fileops.c @@ -0,0 +1,87 @@ +/* _PDCLIB_fileops + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST +#include +#include +#include <_PDCLIB_glue.h> +#include +#include + +#if _PDCLIB_C_MIN(2011) +_Static_assert(SEEK_SET == FILE_BEGIN, "SEEK_SET is incorrect"); +_Static_assert(SEEK_CUR == FILE_CURRENT, "SEEK_CUR is incorrect"); +_Static_assert(SEEK_END == FILE_END, "SEEK_END is incorrect"); +#endif + +void _PDCLIB_w32errno(void); + +static bool readf( _PDCLIB_fd_t self, void * buf, size_t length, + size_t * numBytesRead ) +{ + DWORD dwLen = length > INT32_MAX ? INT32_MAX : length; + DWORD dwBytesRead; + if(ReadFile(self.pointer, buf, dwLen, &dwBytesRead, NULL)) { + *numBytesRead = dwBytesRead; + return true; + } else { + _PDCLIB_w32errno(); + return false; + } +} + +static bool writef( _PDCLIB_fd_t self, const void * buf, size_t length, + size_t * numBytesWritten ) +{ + DWORD dwLen = length > INT32_MAX ? INT32_MAX : length; + DWORD dwBytesWritten; + + if(WriteFile(self.pointer, buf, dwLen, &dwBytesWritten, NULL)) { + *numBytesWritten = dwBytesWritten; + return true; + } else { + _PDCLIB_w32errno(); + return false; + } +} +static bool seekf( _PDCLIB_fd_t self, int_fast64_t offset, int whence, + int_fast64_t* newPos ) +{ + LARGE_INTEGER liOffset; + liOffset.QuadPart = offset; + if(!SetFilePointerEx( self.pointer, liOffset, &liOffset, whence )) { + _PDCLIB_w32errno(); + return false; + } + + *newPos = liOffset.QuadPart; + return true; +} + +static void closef( _PDCLIB_fd_t self ) +{ + CloseHandle( self.pointer ); +} + +const _PDCLIB_fileops_t _PDCLIB_fileops = { + .read = readf, + .write = writef, + .seek = seekf, + .close = closef, +}; + +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + // Tested by stdio test cases + return TEST_RESULTS; +} + +#endif diff --git a/platform/win32/functions/_PDCLIB/_PDCLIB_open.c b/platform/win32/functions/_PDCLIB/_PDCLIB_open.c index a6ac387..af1ee52 100644 --- a/platform/win32/functions/_PDCLIB/_PDCLIB_open.c +++ b/platform/win32/functions/_PDCLIB/_PDCLIB_open.c @@ -16,8 +16,11 @@ #include <_PDCLIB_glue.h> #include +extern const _PDCLIB_fileops_t _PDCLIB_fileops; + void _PDCLIB_w32errno(void); -HANDLE _PDCLIB_open( char const * const filename, unsigned int mode ) +bool _PDCLIB_open( _PDCLIB_fd_t * pFd, const _PDCLIB_fileops_t ** pOps, + char const * const filename, unsigned int mode ) { DWORD desiredAccess; DWORD creationDisposition; @@ -51,7 +54,7 @@ HANDLE _PDCLIB_open( char const * const filename, unsigned int mode ) break; default: /* Invalid mode */ errno = EINVAL; - return NULL; + return false; } HANDLE fd = CreateFileA(filename, desiredAccess, @@ -75,7 +78,7 @@ HANDLE _PDCLIB_open( char const * const filename, unsigned int mode ) fprintf(stderr, "Error: %s\n", msgBuf); #endif _PDCLIB_w32errno(); - return NULL; + return false; } if(mode & _PDCLIB_FAPPEND) { @@ -85,11 +88,13 @@ HANDLE _PDCLIB_open( char const * const filename, unsigned int mode ) if(!ok) { _PDCLIB_w32errno(); CloseHandle(fd); - return NULL; + return false; } } - return fd; + pFd->pointer = fd; + *pOps = &_PDCLIB_fileops; + return true; } #endif diff --git a/platform/win32/functions/_PDCLIB/_PDCLIB_seek.c b/platform/win32/functions/_PDCLIB/_PDCLIB_seek.c deleted file mode 100644 index 6bf53e9..0000000 --- a/platform/win32/functions/_PDCLIB/_PDCLIB_seek.c +++ /dev/null @@ -1,51 +0,0 @@ -/* $Id$ */ - -/* int64_t _PDCLIB_seek( FILE *, int64_t, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include -#include -#ifndef REGTEST -#include <_PDCLIB_glue.h> -#include - -#if _PDCLIB_C_MIN(2011) -_Static_assert(SEEK_SET == FILE_BEGIN, "SEEK_SET is incorrect"); -_Static_assert(SEEK_CUR == FILE_CURRENT, "SEEK_CUR is incorrect"); -_Static_assert(SEEK_END == FILE_END, "SEEK_END is incorrect"); -#endif - -extern void _PDCLIB_w32errno( void ); -_PDCLIB_int64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int64_t offset, int whence ) -{ - LARGE_INTEGER liOffset; - liOffset.QuadPart = offset; - BOOL rv = SetFilePointerEx( stream->handle, liOffset, &liOffset, whence ); - if(!rv) { - _PDCLIB_w32errno(); - return EOF; - } - - stream->ungetidx = 0; - stream->bufidx = 0; - stream->bufend = 0; - stream->pos.offset = liOffset.QuadPart; - return liOffset.QuadPart; -} - -#endif - -#ifdef TEST -#include <_PDCLIB_test.h> - -int main( void ) -{ - /* Testing covered by ftell.c */ - return TEST_RESULTS; -} - -#endif - diff --git a/platform/win32/functions/_PDCLIB/_PDCLIB_stdinit.c b/platform/win32/functions/_PDCLIB/_PDCLIB_stdinit.c index 8eb40f7..6ff9608 100644 --- a/platform/win32/functions/_PDCLIB/_PDCLIB_stdinit.c +++ b/platform/win32/functions/_PDCLIB/_PDCLIB_stdinit.c @@ -17,6 +17,8 @@ #ifndef REGTEST +extern const _PDCLIB_fileops_t _PDCLIB_fileops; + /* In a POSIX system, stdin / stdout / stderr are equivalent to the (int) file descriptors 0, 1, and 2 respectively. */ @@ -29,9 +31,9 @@ static unsigned char _PDCLIB_sin_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; static unsigned char _PDCLIB_sout_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; static unsigned char _PDCLIB_serr_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; -static struct _PDCLIB_file_t _PDCLIB_serr = { NULL, { 0 }, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_serr_ungetbuf, _IONBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, NULL }; -static struct _PDCLIB_file_t _PDCLIB_sout = { NULL, { 0 }, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sout_ungetbuf, _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, &_PDCLIB_serr }; -static struct _PDCLIB_file_t _PDCLIB_sin = { NULL, { 0 }, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sin_ungetbuf, _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, NULL, &_PDCLIB_sout }; +static struct _PDCLIB_file_t _PDCLIB_serr = { &_PDCLIB_fileops, NULL, { 0 }, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_serr_ungetbuf, _IONBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, NULL }; +static struct _PDCLIB_file_t _PDCLIB_sout = { &_PDCLIB_fileops, NULL, { 0 }, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sout_ungetbuf, _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, &_PDCLIB_serr }; +static struct _PDCLIB_file_t _PDCLIB_sin = { &_PDCLIB_fileops, NULL, { 0 }, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sin_ungetbuf, _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, NULL, &_PDCLIB_sout }; struct _PDCLIB_file_t * stdin = &_PDCLIB_sin; struct _PDCLIB_file_t * stdout = &_PDCLIB_sout; diff --git a/platform/win32/functions/stdio/tmpfile.c b/platform/win32/functions/stdio/tmpfile.c index f329234..1b3b4ba 100644 --- a/platform/win32/functions/stdio/tmpfile.c +++ b/platform/win32/functions/stdio/tmpfile.c @@ -16,7 +16,9 @@ static char tmpname_prefix[4] = {0, 0, 0, 0}; +extern const _PDCLIB_fileops_t _PDCLIB_fileops; extern void _PDCLIB_w32errno( void ); + struct _PDCLIB_file_t * tmpfile( void ) { if(!tmpname_prefix[0]) { @@ -67,7 +69,7 @@ struct _PDCLIB_file_t * tmpfile( void ) /* Set the file to delete on close */ DeleteFile(name); - FILE* fs = _PDCLIB_fdopen(fd, _PDCLIB_FWRITE | _PDCLIB_FRW, name); + FILE* fs = _PDCLIB_fvopen(((_PDCLIB_fd_t){fd}), &_PDCLIB_fileops, _PDCLIB_FWRITE | _PDCLIB_FRW, name); if(!fs) { CloseHandle(fd); } diff --git a/platform/win32/internals/_PDCLIB_config.h b/platform/win32/internals/_PDCLIB_config.h index abefef9..57a2d29 100644 --- a/platform/win32/internals/_PDCLIB_config.h +++ b/platform/win32/internals/_PDCLIB_config.h @@ -341,9 +341,6 @@ struct _PDCLIB_imaxdiv_t /* I/O ---------------------------------------------------------------------- */ -/* The type of the file descriptor returned by _PDCLIB_open(). */ -typedef void * _PDCLIB_fd_t; - /* The value (of type _PDCLIB_fd_t) returned by _PDCLIB_open() if the operation failed. */ -- 2.40.0