From 6ca24b75c75b9c6f22e1e69693d326b8e3330841 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Mon, 12 Nov 2012 04:09:02 +0000 Subject: [PATCH 01/16] PDCLIB-16: Add _unlocked variations of all I/O routines; move work into these versions PDCLIB-15: Make most stdio routines lock the stream and then call through to the _unlocked version --- functions/stdio/_PDCLIB_fdopen.c | 1 + functions/stdio/_PDCLIB_ftell64.c | 10 +++++++++- functions/stdio/clearerr.c | 9 ++++++++- functions/stdio/fclose.c | 1 + functions/stdio/feof.c | 10 +++++++++- functions/stdio/ferror.c | 10 +++++++++- functions/stdio/fflush.c | 10 +++++++++- functions/stdio/fgetc.c | 10 +++++++++- functions/stdio/fgetpos.c | 10 +++++++++- functions/stdio/fgets.c | 11 ++++++++++- functions/stdio/fprintf.c | 16 +++++++++++++++- functions/stdio/fputc.c | 10 +++++++++- functions/stdio/fputs.c | 12 +++++++++++- functions/stdio/fread.c | 14 +++++++++++++- functions/stdio/freopen.c | 13 ++++++++++++- functions/stdio/fscanf.c | 14 +++++++++++++- functions/stdio/fseek.c | 10 +++++++++- functions/stdio/fsetpos.c | 12 +++++++++++- functions/stdio/ftell.c | 12 ++++++++++-- functions/stdio/fwrite.c | 14 +++++++++++++- functions/stdio/getc.c | 5 +++++ functions/stdio/getchar.c | 6 ++++++ functions/stdio/printf.c | 10 ++++++++++ functions/stdio/putc.c | 6 ++++++ functions/stdio/putchar.c | 5 +++++ functions/stdio/puts.c | 10 +++++++++- functions/stdio/scanf.c | 7 +++++++ functions/stdio/ungetc.c | 10 +++++++++- functions/stdio/vfprintf.c | 14 +++++++++++++- functions/stdio/vfscanf.c | 14 +++++++++++++- functions/stdio/vprintf.c | 6 ++++++ functions/stdio/vscanf.c | 5 +++++ functions/stdio/vsnprintf.c | 5 ++++- functions/stdio/vsprintf.c | 4 +++- functions/stdio/vsscanf.c | 4 +++- includes/stdio.h | 26 +++++++++++++++++++++++++- 36 files changed, 319 insertions(+), 27 deletions(-) diff --git a/functions/stdio/_PDCLIB_fdopen.c b/functions/stdio/_PDCLIB_fdopen.c index 7b53952..c628ebc 100644 --- a/functions/stdio/_PDCLIB_fdopen.c +++ b/functions/stdio/_PDCLIB_fdopen.c @@ -12,6 +12,7 @@ #ifndef REGTEST #include <_PDCLIB_glue.h> #include +#include extern struct _PDCLIB_file_t * _PDCLIB_filelist; diff --git a/functions/stdio/_PDCLIB_ftell64.c b/functions/stdio/_PDCLIB_ftell64.c index 650eda5..e0ea368 100644 --- a/functions/stdio/_PDCLIB_ftell64.c +++ b/functions/stdio/_PDCLIB_ftell64.c @@ -12,7 +12,7 @@ #ifndef REGTEST -uint_fast64_t _PDCLIB_ftell64( struct _PDCLIB_file_t * stream ) +uint_fast64_t _PDCLIB_ftell64_unlocked( struct _PDCLIB_file_t * stream ) { /* ftell() must take into account: - the actual *physical* offset of the file, i.e. the offset as recognized @@ -38,6 +38,14 @@ uint_fast64_t _PDCLIB_ftell64( struct _PDCLIB_file_t * stream ) return ( stream->pos.offset - ( ( (int)stream->bufend - (int)stream->bufidx ) + (int)stream->ungetidx ) ); } +uint_fast64_t _PDCLIB_ftell64( struct _PDCLIB_file_t * stream ) +{ + flockfile( stream ); + uint_fast64_t pos = _PDCLIB_ftell64_unlocked( stream ); + funlockfile( stream ); + return pos; +} + #endif #ifdef TEST diff --git a/functions/stdio/clearerr.c b/functions/stdio/clearerr.c index af50f14..2b032bd 100644 --- a/functions/stdio/clearerr.c +++ b/functions/stdio/clearerr.c @@ -10,11 +10,18 @@ #ifndef REGTEST -void clearerr( struct _PDCLIB_file_t * stream ) +void clearerr_unlocked( struct _PDCLIB_file_t * stream ) { stream->status &= ~( _PDCLIB_ERRORFLAG | _PDCLIB_EOFFLAG ); } +void clearerr( struct _PDCLIB_file_t * stream ) +{ + flockfile( stream ); + clearerr_unlocked( stream ); + funlockfile( stream ); +} + #endif #ifdef TEST diff --git a/functions/stdio/fclose.c b/functions/stdio/fclose.c index dbd7f6e..c4f5d8a 100644 --- a/functions/stdio/fclose.c +++ b/functions/stdio/fclose.c @@ -12,6 +12,7 @@ #ifndef REGTEST #include <_PDCLIB_glue.h> +#include extern struct _PDCLIB_file_t * _PDCLIB_filelist; diff --git a/functions/stdio/feof.c b/functions/stdio/feof.c index d5cf188..ca43c75 100644 --- a/functions/stdio/feof.c +++ b/functions/stdio/feof.c @@ -10,11 +10,19 @@ #ifndef REGTEST -int feof( struct _PDCLIB_file_t * stream ) +int feof_unlocked( struct _PDCLIB_file_t * stream ) { return stream->status & _PDCLIB_EOFFLAG; } +int feof( struct _PDCLIB_file_t * stream ) +{ + flockfile( stream ); + int eof = feof_unlocked( stream ); + funlockfile( stream ); + return eof; +} + #endif #ifdef TEST diff --git a/functions/stdio/ferror.c b/functions/stdio/ferror.c index 7ca531e..394dcda 100644 --- a/functions/stdio/ferror.c +++ b/functions/stdio/ferror.c @@ -10,11 +10,19 @@ #ifndef REGTEST -int ferror( struct _PDCLIB_file_t * stream ) +int ferror_unlocked( struct _PDCLIB_file_t * stream ) { return stream->status & _PDCLIB_ERRORFLAG; } +int ferror( struct _PDCLIB_file_t * stream ) +{ + flockfile( stream ); + int error = ferror_unlocked( stream ); + funlockfile( stream ); + return error; +} + #endif #ifdef TEST diff --git a/functions/stdio/fflush.c b/functions/stdio/fflush.c index b8d32ec..df45880 100644 --- a/functions/stdio/fflush.c +++ b/functions/stdio/fflush.c @@ -13,7 +13,7 @@ extern struct _PDCLIB_file_t * _PDCLIB_filelist; -int fflush( struct _PDCLIB_file_t * stream ) +int fflush_unlocked( struct _PDCLIB_file_t * stream ) { if ( stream == NULL ) { @@ -38,6 +38,14 @@ int fflush( struct _PDCLIB_file_t * stream ) return _PDCLIB_flushbuffer( stream ); } } + +int fflush( struct _PDCLIB_file_t * stream ) +{ + flockfile( stream ); + int res = fflush_unlocked(stream); + funlockfile( stream ); + return res; +} #endif diff --git a/functions/stdio/fgetc.c b/functions/stdio/fgetc.c index 29522c1..ae7a835 100644 --- a/functions/stdio/fgetc.c +++ b/functions/stdio/fgetc.c @@ -12,7 +12,7 @@ #include <_PDCLIB_glue.h> -int fgetc( struct _PDCLIB_file_t * stream ) +int fgetc_unlocked( struct _PDCLIB_file_t * stream ) { if ( _PDCLIB_prepread( stream ) == EOF ) { @@ -25,6 +25,14 @@ int fgetc( struct _PDCLIB_file_t * stream ) return (unsigned char)stream->buffer[stream->bufidx++]; } +int fgetc( struct _PDCLIB_file_t * stream ) +{ + flockfile( stream ); + int c = fgetc_unlocked( stream ); + funlockfile( stream ); + return c; +} + #endif #ifdef TEST diff --git a/functions/stdio/fgetpos.c b/functions/stdio/fgetpos.c index 3e41c40..28352c8 100644 --- a/functions/stdio/fgetpos.c +++ b/functions/stdio/fgetpos.c @@ -10,7 +10,7 @@ #ifndef REGTEST -int fgetpos( struct _PDCLIB_file_t * _PDCLIB_restrict stream, struct _PDCLIB_fpos_t * _PDCLIB_restrict pos ) +int fgetpos_unlocked( struct _PDCLIB_file_t * _PDCLIB_restrict stream, struct _PDCLIB_fpos_t * _PDCLIB_restrict pos ) { pos->offset = stream->pos.offset + stream->bufidx - stream->ungetidx; pos->status = stream->pos.status; @@ -18,6 +18,14 @@ int fgetpos( struct _PDCLIB_file_t * _PDCLIB_restrict stream, struct _PDCLIB_fpo return 0; } +int fgetpos( struct _PDCLIB_file_t * _PDCLIB_restrict stream, struct _PDCLIB_fpos_t * _PDCLIB_restrict pos ) +{ + flockfile( stream ); + int res = fgetpos_unlocked( stream, pos ); + funlockfile( stream ); + return res; +} + #endif #ifdef TEST diff --git a/functions/stdio/fgets.c b/functions/stdio/fgets.c index 44518a3..0451058 100644 --- a/functions/stdio/fgets.c +++ b/functions/stdio/fgets.c @@ -12,7 +12,7 @@ #include <_PDCLIB_glue.h> -char * fgets( char * _PDCLIB_restrict s, int size, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +char * fgets_unlocked( char * _PDCLIB_restrict s, int size, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) { if ( size == 0 ) { @@ -46,6 +46,15 @@ char * fgets( char * _PDCLIB_restrict s, int size, struct _PDCLIB_file_t * _PDCL return ( dest == s ) ? NULL : s; } +char * fgets( char * _PDCLIB_restrict s, int size, + struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +{ + flockfile( stream ); + char* r = fgets_unlocked( s, size, stream ); + funlockfile( stream ); + return r; +} + #endif #ifdef TEST diff --git a/functions/stdio/fprintf.c b/functions/stdio/fprintf.c index cb922ba..421ca52 100644 --- a/functions/stdio/fprintf.c +++ b/functions/stdio/fprintf.c @@ -11,7 +11,8 @@ #ifndef REGTEST -int fprintf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) +int fprintf_unlocked( struct _PDCLIB_file_t * _PDCLIB_restrict stream, + const char * _PDCLIB_restrict format, ... ) { int rc; va_list ap; @@ -21,6 +22,19 @@ int fprintf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, const char * _PDCL return rc; } +int fprintf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, + const char * _PDCLIB_restrict format, ... ) +{ + int rc; + va_list ap; + va_start( ap, format ); + flockfile( stream ); + rc = vfprintf_unlocked( stream, format, ap ); + funlockfile( stream ); + va_end( ap ); + return rc; +} + #endif #ifdef TEST diff --git a/functions/stdio/fputc.c b/functions/stdio/fputc.c index 818d45f..ae998ea 100644 --- a/functions/stdio/fputc.c +++ b/functions/stdio/fputc.c @@ -16,7 +16,7 @@ Returns c if successful, EOF otherwise. If a write error occurs, the error indicator of the stream is set. */ -int fputc( int c, struct _PDCLIB_file_t * stream ) +int fputc_unlocked( int c, struct _PDCLIB_file_t * stream ) { if ( _PDCLIB_prepwrite( stream ) == EOF ) { @@ -34,6 +34,14 @@ int fputc( int c, struct _PDCLIB_file_t * stream ) return c; } +int fputc( int c, struct _PDCLIB_file_t * stream ) +{ + flockfile( stream ); + int r = fputc_unlocked( c, stream ); + funlockfile( stream ); + return r; +} + #endif #ifdef TEST diff --git a/functions/stdio/fputs.c b/functions/stdio/fputs.c index 2c5e1fa..0b1e325 100644 --- a/functions/stdio/fputs.c +++ b/functions/stdio/fputs.c @@ -11,7 +11,8 @@ #ifndef REGTEST #include <_PDCLIB_glue.h> -int fputs( const char * _PDCLIB_restrict s, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +int fputs_unlocked( const char * _PDCLIB_restrict s, + struct _PDCLIB_file_t * _PDCLIB_restrict stream ) { if ( _PDCLIB_prepwrite( stream ) == EOF ) { @@ -45,6 +46,15 @@ int fputs( const char * _PDCLIB_restrict s, struct _PDCLIB_file_t * _PDCLIB_rest return 0; } +int fputs( const char * _PDCLIB_restrict s, + struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +{ + flockfile( stream ); + int r = fputs_unlocked( s, stream ); + funlockfile( stream ); + return r; +} + #endif #ifdef TEST #include <_PDCLIB_test.h> diff --git a/functions/stdio/fread.c b/functions/stdio/fread.c index 9f7d3fa..1fdc753 100644 --- a/functions/stdio/fread.c +++ b/functions/stdio/fread.c @@ -15,7 +15,9 @@ #include #include -size_t fread( void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +size_t fread_unlocked( void * _PDCLIB_restrict ptr, + size_t size, size_t nmemb, + struct _PDCLIB_file_t * _PDCLIB_restrict stream ) { if ( _PDCLIB_prepread( stream ) == EOF ) { @@ -41,6 +43,16 @@ size_t fread( void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, struct _PD return nmemb_i; } +size_t fread( void * _PDCLIB_restrict ptr, + size_t size, size_t nmemb, + struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +{ + flockfile( stream ); + size_t r = fread_unlocked( ptr, size, nmemb, stream ); + funlockfile( stream ); + return r; +} + #endif #ifdef TEST diff --git a/functions/stdio/freopen.c b/functions/stdio/freopen.c index 682e3c6..7868c95 100644 --- a/functions/stdio/freopen.c +++ b/functions/stdio/freopen.c @@ -14,8 +14,13 @@ #include #include -struct _PDCLIB_file_t * freopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +struct _PDCLIB_file_t * freopen( + const char * _PDCLIB_restrict filename, + const char * _PDCLIB_restrict mode, + struct _PDCLIB_file_t * _PDCLIB_restrict stream ) { + flockfile( stream ); + unsigned int status = stream->status & ( _IONBF | _IOLBF | _IOFBF | _PDCLIB_FREEBUFFER | _PDCLIB_DELONCLOSE ); /* TODO: This function can change wide orientation of a stream */ if ( stream->status & _PDCLIB_FWRITE ) @@ -25,6 +30,7 @@ struct _PDCLIB_file_t * freopen( const char * _PDCLIB_restrict filename, const c if ( ( filename == NULL ) && ( stream->filename == NULL ) ) { /* TODO: Special handling for mode changes on std-streams */ + funlockfile( stream ); return NULL; } _PDCLIB_close( stream->handle ); @@ -49,16 +55,19 @@ struct _PDCLIB_file_t * freopen( const char * _PDCLIB_restrict filename, const c /* Allocate new buffer */ if ( ( stream->filename = (char *)malloc( strlen( filename ) ) ) == NULL ) { + funlockfile( stream ); return NULL; } strcpy( stream->filename, filename ); } if ( ( mode == NULL ) || ( filename[0] == '\0' ) ) { + funlockfile( stream ); return NULL; } if ( ( stream->status = _PDCLIB_filemode( mode ) ) == 0 ) { + funlockfile( stream ); return NULL; } /* Re-add the flags we saved above */ @@ -69,8 +78,10 @@ struct _PDCLIB_file_t * freopen( const char * _PDCLIB_restrict filename, const c /* TODO: Setting mbstate */ if ( ( stream->handle = _PDCLIB_open( filename, stream->status ) ) == _PDCLIB_NOHANDLE ) { + funlockfile( stream ); return NULL; } + funlockfile( stream ); return stream; } diff --git a/functions/stdio/fscanf.c b/functions/stdio/fscanf.c index 6c0c70b..fbe280b 100644 --- a/functions/stdio/fscanf.c +++ b/functions/stdio/fscanf.c @@ -11,7 +11,19 @@ #ifndef REGTEST -int fscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) +int fscanf_unlocked( FILE * _PDCLIB_restrict stream, + const char * _PDCLIB_restrict format, ... ) +{ + int rc; + va_list ap; + va_start( ap, format ); + rc = vfscanf_unlocked( stream, format, ap ); + va_end( ap ); + return rc; +} + +int fscanf( FILE * _PDCLIB_restrict stream, + const char * _PDCLIB_restrict format, ... ) { int rc; va_list ap; diff --git a/functions/stdio/fseek.c b/functions/stdio/fseek.c index 8e10c2b..c897325 100644 --- a/functions/stdio/fseek.c +++ b/functions/stdio/fseek.c @@ -12,7 +12,7 @@ #include <_PDCLIB_glue.h> -int fseek( struct _PDCLIB_file_t * stream, long loffset, int whence ) +int fseek_unlocked( struct _PDCLIB_file_t * stream, long loffset, int whence ) { _PDCLIB_int64_t offset = loffset; if ( stream->status & _PDCLIB_FWRITE ) @@ -37,6 +37,14 @@ int fseek( struct _PDCLIB_file_t * stream, long loffset, int whence ) return ( _PDCLIB_seek( stream, offset, whence ) != EOF ) ? 0 : EOF; } +int fseek( struct _PDCLIB_file_t * stream, long loffset, int whence ) +{ + flockfile( stream ); + int r = fseek_unlocked( stream, loffset, whence ); + funlockfile( stream ); + return r; +} + #endif #ifdef TEST diff --git a/functions/stdio/fsetpos.c b/functions/stdio/fsetpos.c index 2082b48..aa2f8e6 100644 --- a/functions/stdio/fsetpos.c +++ b/functions/stdio/fsetpos.c @@ -11,7 +11,8 @@ #ifndef REGTEST #include <_PDCLIB_glue.h> -int fsetpos( struct _PDCLIB_file_t * stream, const struct _PDCLIB_fpos_t * pos ) +int fsetpos_unlocked( struct _PDCLIB_file_t * stream, + const struct _PDCLIB_fpos_t * pos ) { if ( stream->status & _PDCLIB_FWRITE ) { @@ -29,6 +30,15 @@ int fsetpos( struct _PDCLIB_file_t * stream, const struct _PDCLIB_fpos_t * pos ) return 0; } +int fsetpos( struct _PDCLIB_file_t * stream, + const struct _PDCLIB_fpos_t * pos ) +{ + flockfile( stream ); + int res = fsetpos_unlocked( stream, pos ); + funlockfile( stream ); + return res; +} + #endif #ifdef TEST diff --git a/functions/stdio/ftell.c b/functions/stdio/ftell.c index d39297f..74bb902 100644 --- a/functions/stdio/ftell.c +++ b/functions/stdio/ftell.c @@ -13,9 +13,9 @@ #ifndef REGTEST -long int ftell( struct _PDCLIB_file_t * stream ) +long int ftell_unlocked( struct _PDCLIB_file_t * stream ) { - uint_fast64_t off64 = _PDCLIB_ftell64( stream ); + uint_fast64_t off64 = _PDCLIB_ftell64_unlocked( stream ); if ( off64 > LONG_MAX ) { @@ -26,6 +26,14 @@ long int ftell( struct _PDCLIB_file_t * stream ) return off64; } +long int ftell( struct _PDCLIB_file_t * stream ) +{ + flockfile( stream ); + long int off = ftell_unlocked( stream ); + funlockfile( stream ); + return off; +} + #endif #ifdef TEST diff --git a/functions/stdio/fwrite.c b/functions/stdio/fwrite.c index 90c8f44..9ab8a0a 100644 --- a/functions/stdio/fwrite.c +++ b/functions/stdio/fwrite.c @@ -17,7 +17,9 @@ //TODO OS(2012-08-01): Ascertain purpose of lineend & potentially remove -size_t fwrite( const void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +size_t fwrite_unlocked( const void * _PDCLIB_restrict ptr, + size_t size, size_t nmemb, + struct _PDCLIB_file_t * _PDCLIB_restrict stream ) { if ( _PDCLIB_prepwrite( stream ) == EOF ) { @@ -88,6 +90,16 @@ size_t fwrite( const void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, str return nmemb_i; } +size_t fwrite( const void * _PDCLIB_restrict ptr, + size_t size, size_t nmemb, + struct _PDCLIB_file_t * _PDCLIB_restrict stream ) +{ + flockfile( stream ); + size_t r = fwrite_unlocked( ptr, size, nmemb, stream ); + funlockfile( stream ); + return r; +} + #endif #ifdef TEST diff --git a/functions/stdio/getc.c b/functions/stdio/getc.c index a459c22..9338baf 100644 --- a/functions/stdio/getc.c +++ b/functions/stdio/getc.c @@ -10,6 +10,11 @@ #ifndef REGTEST +int getc_unlocked( struct _PDCLIB_file_t * stream ) +{ + return fgetc_unlocked( stream ); +} + int getc( struct _PDCLIB_file_t * stream ) { return fgetc( stream ); diff --git a/functions/stdio/getchar.c b/functions/stdio/getchar.c index 1603728..406abe4 100644 --- a/functions/stdio/getchar.c +++ b/functions/stdio/getchar.c @@ -10,6 +10,12 @@ #ifndef REGTEST +int getchar_unlocked( void ) +{ + return fgetc_unlocked( stdin ); +} + + int getchar( void ) { return fgetc( stdin ); diff --git a/functions/stdio/printf.c b/functions/stdio/printf.c index 122f8df..a4efd6a 100644 --- a/functions/stdio/printf.c +++ b/functions/stdio/printf.c @@ -21,6 +21,16 @@ int printf( const char * _PDCLIB_restrict format, ... ) return rc; } +int printf_unlocked( const char * _PDCLIB_restrict format, ... ) +{ + int rc; + va_list ap; + va_start( ap, format ); + rc = vfprintf_unlocked( stdout, format, ap ); + va_end( ap ); + return rc; +} + #endif #ifdef TEST diff --git a/functions/stdio/putc.c b/functions/stdio/putc.c index 60a4dba..c1f3fc2 100644 --- a/functions/stdio/putc.c +++ b/functions/stdio/putc.c @@ -10,6 +10,12 @@ #ifndef REGTEST +int putc_unlocked( int c, struct _PDCLIB_file_t * stream ) +{ + return fputc_unlocked( c, stream ); +} + + int putc( int c, struct _PDCLIB_file_t * stream ) { return fputc( c, stream ); diff --git a/functions/stdio/putchar.c b/functions/stdio/putchar.c index 4e2d6ae..52063a5 100644 --- a/functions/stdio/putchar.c +++ b/functions/stdio/putchar.c @@ -10,6 +10,11 @@ #ifndef REGTEST +int putchar_unlocked( int c ) +{ + return fputc_unlocked( c, stdout ); +} + int putchar( int c ) { return fputc( c, stdout ); diff --git a/functions/stdio/puts.c b/functions/stdio/puts.c index ec67478..4e55226 100644 --- a/functions/stdio/puts.c +++ b/functions/stdio/puts.c @@ -13,7 +13,7 @@ extern char * _PDCLIB_eol; -int puts( const char * s ) +int puts_unlocked( const char * s ) { if ( _PDCLIB_prepwrite( stdout ) == EOF ) { @@ -42,6 +42,14 @@ int puts( const char * s ) } } +int puts( const char * s ) +{ + flockfile( stdout ); + int r = puts_unlocked( s ); + funlockfile( stdout ); + return r; +} + #endif #ifdef TEST diff --git a/functions/stdio/scanf.c b/functions/stdio/scanf.c index 41501bc..e11ccbd 100644 --- a/functions/stdio/scanf.c +++ b/functions/stdio/scanf.c @@ -11,6 +11,13 @@ #ifndef REGTEST +int scanf_unlocked( const char * _PDCLIB_restrict format, ... ) +{ + va_list ap; + va_start( ap, format ); + return vfscanf_unlocked( stdin, format, ap ); +} + int scanf( const char * _PDCLIB_restrict format, ... ) { va_list ap; diff --git a/functions/stdio/ungetc.c b/functions/stdio/ungetc.c index 001735b..45b8a92 100644 --- a/functions/stdio/ungetc.c +++ b/functions/stdio/ungetc.c @@ -10,7 +10,7 @@ #ifndef REGTEST -int ungetc( int c, struct _PDCLIB_file_t * stream ) +int ungetc_unlocked( int c, struct _PDCLIB_file_t * stream ) { if ( c == EOF || stream->ungetidx == _PDCLIB_UNGETCBUFSIZE ) { @@ -19,6 +19,14 @@ int ungetc( int c, struct _PDCLIB_file_t * stream ) return stream->ungetbuf[stream->ungetidx++] = (unsigned char) c; } +int ungetc( int c, struct _PDCLIB_file_t * stream ) +{ + flockfile( stream ); + int r = ungetc_unlocked( c, stream ); + funlockfile( stream); + return r; +} + #endif #ifdef TEST diff --git a/functions/stdio/vfprintf.c b/functions/stdio/vfprintf.c index cc6e7a6..ffb4bbe 100644 --- a/functions/stdio/vfprintf.c +++ b/functions/stdio/vfprintf.c @@ -12,7 +12,9 @@ #ifndef REGTEST -int vfprintf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, va_list arg ) +int vfprintf_unlocked( struct _PDCLIB_file_t * _PDCLIB_restrict stream, + const char * _PDCLIB_restrict format, + va_list arg ) { /* TODO: This function should interpret format as multibyte characters. */ struct _PDCLIB_status_t status; @@ -46,6 +48,16 @@ int vfprintf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, const char * _PDC return status.i; } +int vfprintf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, + const char * _PDCLIB_restrict format, + va_list arg ) +{ + flockfile( stream ); + int r = vfprintf_unlocked( stream, format, arg ); + funlockfile( stream ); + return r; +} + #endif #ifdef TEST diff --git a/functions/stdio/vfscanf.c b/functions/stdio/vfscanf.c index b9a6896..da365bd 100644 --- a/functions/stdio/vfscanf.c +++ b/functions/stdio/vfscanf.c @@ -12,7 +12,9 @@ #ifndef REGTEST -int vfscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, va_list arg ) +int vfscanf_unlocked( FILE * _PDCLIB_restrict stream, + const char * _PDCLIB_restrict format, + va_list arg ) { /* TODO: This function should interpret format as multibyte characters. */ struct _PDCLIB_status_t status; @@ -85,6 +87,16 @@ int vfscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict forma return status.n; } +int vfscanf( FILE * _PDCLIB_restrict stream, + const char * _PDCLIB_restrict format, + va_list arg ) +{ + flockfile( stream ); + int r = vfscanf_unlocked( stream, format, arg ); + funlockfile( stream ); + return r; +} + #endif #ifdef TEST diff --git a/functions/stdio/vprintf.c b/functions/stdio/vprintf.c index 48ad557..6eba229 100644 --- a/functions/stdio/vprintf.c +++ b/functions/stdio/vprintf.c @@ -11,6 +11,12 @@ #ifndef REGTEST +int vprintf_unlocked( const char * _PDCLIB_restrict format, + _PDCLIB_va_list arg ) +{ + return vfprintf_unlocked( stdout, format, arg ); +} + int vprintf( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) { return vfprintf( stdout, format, arg ); diff --git a/functions/stdio/vscanf.c b/functions/stdio/vscanf.c index 0b9189d..dc3a236 100644 --- a/functions/stdio/vscanf.c +++ b/functions/stdio/vscanf.c @@ -11,6 +11,11 @@ #ifndef REGTEST +int vscanf_unlocked( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) +{ + return vfscanf_unlocked( stdin, format, arg ); +} + int vscanf( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) { return vfscanf( stdin, format, arg ); diff --git a/functions/stdio/vsnprintf.c b/functions/stdio/vsnprintf.c index 06536d1..64a0651 100644 --- a/functions/stdio/vsnprintf.c +++ b/functions/stdio/vsnprintf.c @@ -11,7 +11,10 @@ #ifndef REGTEST -int vsnprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) +int vsnprintf( char * _PDCLIB_restrict s, + size_t n, + const char * _PDCLIB_restrict format, + _PDCLIB_va_list arg ) { /* TODO: This function should interpret format as multibyte characters. */ struct _PDCLIB_status_t status; diff --git a/functions/stdio/vsprintf.c b/functions/stdio/vsprintf.c index 3dfe3c2..5f08688 100644 --- a/functions/stdio/vsprintf.c +++ b/functions/stdio/vsprintf.c @@ -12,7 +12,9 @@ #ifndef REGTEST -int vsprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, va_list arg ) +int vsprintf( char * _PDCLIB_restrict s, + const char * _PDCLIB_restrict format, + va_list arg ) { return vsnprintf( s, SIZE_MAX, format, arg ); /* TODO: Replace with a non-checking call */ } diff --git a/functions/stdio/vsscanf.c b/functions/stdio/vsscanf.c index 4300a3e..99b8bad 100644 --- a/functions/stdio/vsscanf.c +++ b/functions/stdio/vsscanf.c @@ -12,7 +12,9 @@ #ifndef REGTEST #include -int vsscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, va_list arg ) +int vsscanf( const char * _PDCLIB_restrict s, + const char * _PDCLIB_restrict format, + va_list arg ) { /* TODO: This function should interpret format as multibyte characters. */ struct _PDCLIB_status_t status; diff --git a/includes/stdio.h b/includes/stdio.h index acc0012..79a54bd 100644 --- a/includes/stdio.h +++ b/includes/stdio.h @@ -788,7 +788,6 @@ int fsetpos( FILE * stream, const fpos_t * pos ) _PDCLIB_nothrow; TODO: Implementation-defined errno setting for ftell(). */ long int ftell( FILE * stream ) _PDCLIB_nothrow; -_PDCLIB_uint_fast64_t _PDCLIB_ftell64( FILE * stream ) _PDCLIB_nothrow; /* Equivalent to (void)fseek( stream, 0L, SEEK_SET ), except that the error indicator for the stream is also cleared. @@ -861,5 +860,30 @@ char *fgets_unlocked(char *s, int n, FILE *stream); int fputs_unlocked(const char *s, FILE *stream); #endif +#if defined(_PDCLIB_EXTENSIONS) +int fgetpos_unlocked( FILE * _PDCLIB_restrict stream, fpos_t * _PDCLIB_restrict pos ) _PDCLIB_nothrow; +int fsetpos_unlocked( FILE * stream, const fpos_t * pos ) _PDCLIB_nothrow; +long int ftell_unlocked( FILE * stream ) _PDCLIB_nothrow; +int fseek_unlocked( FILE * stream, long int offset, int whence ) _PDCLIB_nothrow; + +int puts_unlocked( const char * s ) _PDCLIB_nothrow; +int ungetc_unlocked( int c, FILE * stream ) _PDCLIB_nothrow; + + +int printf_unlocked( const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow; +int vprintf_unlocked( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow; +int fprintf_unlocked( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow; +int vfprintf_unlocked( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow; +int scanf_unlocked( const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow; +int vscanf_unlocked( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow; +int fscanf_unlocked( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow; +int vfscanf_unlocked( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow; + + +// Todo: remove prefix? +_PDCLIB_uint_fast64_t _PDCLIB_ftell64( FILE * stream ) _PDCLIB_nothrow; +_PDCLIB_uint_fast64_t _PDCLIB_ftell64_unlocked( FILE * stream ) _PDCLIB_nothrow; +#endif + _PDCLIB_END_EXTERN_C #endif -- 2.40.0 From eb6f9c3c6065ad3975d69630d622d91374784806 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Thu, 15 Nov 2012 20:03:28 +0000 Subject: [PATCH 02/16] PDCLIB-15: _PDCLIB_print now calls through to putc_unlocked --- functions/_PDCLIB/print.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/_PDCLIB/print.c b/functions/_PDCLIB/print.c index aa39707..dcdb7bd 100644 --- a/functions/_PDCLIB/print.c +++ b/functions/_PDCLIB/print.c @@ -53,7 +53,7 @@ do { \ int character = x; \ if ( status->i < status->n ) { \ if ( status->stream != NULL ) \ - putc( character, status->stream ); \ + putc_unlocked( character, status->stream ); \ else \ status->s[status->i] = character; \ } \ -- 2.40.0 From 01084b6a95bd991aa227977e96c9aa1b8e08ef85 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Thu, 15 Nov 2012 20:33:02 +0000 Subject: [PATCH 03/16] win32: Fix warnings relating to definition of LONG and use of InterlockedCompareExchange --- platform/win32/functions/threads/mtx_lock.c | 2 +- platform/win32/functions/threads/mtx_timedlock.c | 2 +- platform/win32/functions/threads/mtx_trylock.c | 2 +- platform/win32/internals/_PDCLIB_threadconfig.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/win32/functions/threads/mtx_lock.c b/platform/win32/functions/threads/mtx_lock.c index 59e716d..d16a487 100644 --- a/platform/win32/functions/threads/mtx_lock.c +++ b/platform/win32/functions/threads/mtx_lock.c @@ -6,7 +6,7 @@ int mtx_lock(mtx_t *mtx) { DWORD myId = GetCurrentThreadId(); - if(mtx->_ThreadId == myId) { + if(mtx->_ThreadId == (long) myId) { mtx->_NestCount++; return thrd_success; } diff --git a/platform/win32/functions/threads/mtx_timedlock.c b/platform/win32/functions/threads/mtx_timedlock.c index 07edc0c..5c1ffb3 100644 --- a/platform/win32/functions/threads/mtx_timedlock.c +++ b/platform/win32/functions/threads/mtx_timedlock.c @@ -8,7 +8,7 @@ int mtx_timedlock(mtx_t *_PDCLIB_restrict mtx, { DWORD myId = GetCurrentThreadId(); - if(mtx->_ThreadId == myId) { + if(mtx->_ThreadId == (long) myId) { mtx->_NestCount++; return thrd_success; } diff --git a/platform/win32/functions/threads/mtx_trylock.c b/platform/win32/functions/threads/mtx_trylock.c index ebc5e85..c5fce0e 100644 --- a/platform/win32/functions/threads/mtx_trylock.c +++ b/platform/win32/functions/threads/mtx_trylock.c @@ -6,7 +6,7 @@ int mtx_trylock(mtx_t *mtx) { DWORD myId = GetCurrentThreadId(); - if(mtx->_ThreadId == myId) { + if(mtx->_ThreadId == (long) myId) { mtx->_NestCount++; return thrd_success; } diff --git a/platform/win32/internals/_PDCLIB_threadconfig.h b/platform/win32/internals/_PDCLIB_threadconfig.h index c311867..0f35d29 100644 --- a/platform/win32/internals/_PDCLIB_threadconfig.h +++ b/platform/win32/internals/_PDCLIB_threadconfig.h @@ -20,7 +20,7 @@ void _PDCLIB_call_once(_PDCLIB_once_flag *flag, void (*func)(void)); struct _PDCLIB_mtx { void * _WaitEvHandle; - volatile unsigned long _ThreadId; + volatile long _ThreadId; volatile unsigned int _NestCount; }; -- 2.40.0 From 4c7c56442f6b3e08c17594dd4e8095fca3aec9cf Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Tue, 4 Dec 2012 19:07:13 +0000 Subject: [PATCH 04/16] On C++, define _PDCLIB_wchar_t to be builtin type wchar_t --- internals/_PDCLIB_int.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internals/_PDCLIB_int.h b/internals/_PDCLIB_int.h index da20dfe..601525e 100644 --- a/internals/_PDCLIB_int.h +++ b/internals/_PDCLIB_int.h @@ -231,7 +231,11 @@ typedef _PDCLIB_size _PDCLIB_size_t; #define _PDCLIB_SIZE_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_SIZE ), _MAX ) typedef _PDCLIB_wint _PDCLIB_wint_t; -typedef _PDCLIB_wchar _PDCLIB_wchar_t; +#ifndef __cplusplus + typedef _PDCLIB_wchar _PDCLIB_wchar_t; +#else + typedef wchar_t _PDCLIB_wchar_t; +#endif #define _PDCLIB_WCHAR_MIN _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_WCHAR ), _MIN ) #define _PDCLIB_WCHAR_MAX _PDCLIB_concat( _PDCLIB_concat( _PDCLIB_, _PDCLIB_WCHAR ), _MAX ) -- 2.40.0 From c5d49235e09fbd58416f10dec2799e61cf3431c8 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Wed, 5 Dec 2012 02:20:16 +0000 Subject: [PATCH 05/16] 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 From 59953f20c461a26fd6f0be8c28c784709da51a5e Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Tue, 11 Dec 2012 00:55:36 +0000 Subject: [PATCH 06/16] PDCLIB-18: Implement defect test cases --- functions/stdio/ungetc.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/functions/stdio/ungetc.c b/functions/stdio/ungetc.c index 45b8a92..2e556ab 100644 --- a/functions/stdio/ungetc.c +++ b/functions/stdio/ungetc.c @@ -32,9 +32,35 @@ int ungetc( int c, struct _PDCLIB_file_t * stream ) #ifdef TEST #include <_PDCLIB_test.h> +const char* hellostr = "Hello, world!"; + int main( void ) { - /* Testing covered by ftell.c */ + // Also see ftell() for some testing + + // PDCLIB-18: fread ignores ungetc + size_t bufsz = strlen( hellostr ) + 1; + char * buf = malloc( bufsz ); + FILE * fh; + + // Also fgets + TESTCASE( ( fh = tmpfile() ) != NULL ); + TESTCASE( fputs(hellostr, fh) == 0 ); + rewind(fh); + TESTCASE( fgetc( fh ) == 'H' ); + TESTCASE( ungetc( 'H', fh ) == 'H' ); + TESTCASE( fgets( buf, bufsz, fh ) != NULL ); + TESTCASE( strcmp( buf, hellostr ) == 0 ); + + // fread + rewind(fh); + TESTCASE( fgetc( fh ) == 'H' ); + TESTCASE( ungetc( 'H', fh ) == 'H' ); + TESTCASE( fread( buf, bufsz - 1, 1, fh ) == 1 ); + TESTCASE( strncmp( buf, hellostr, bufsz - 1 ) == 0 ); + + + return TEST_RESULTS; } -- 2.40.0 From 7f9e4ed1a81518df0aed2dfe2b18ee12dbadfa79 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Tue, 11 Dec 2012 01:15:02 +0000 Subject: [PATCH 07/16] PDCLIB-19: Remove gets() when >=C11. Deprecated it universally. --- includes/stdio.h | 7 ++- internals/_PDCLIB_aux.h | 108 +++++++++++++++++++++------------------- 2 files changed, 64 insertions(+), 51 deletions(-) diff --git a/includes/stdio.h b/includes/stdio.h index 9d423c1..9dc09f1 100644 --- a/includes/stdio.h +++ b/includes/stdio.h @@ -684,13 +684,18 @@ int getc( FILE * stream ) _PDCLIB_nothrow; /* Equivalent to fgetc( stdin ). */ int getchar( void ) _PDCLIB_nothrow; +#if _PDCLIB_C_MAX(1999) /* Read characters from given stream into the array s, stopping at \n or EOF. The string read is terminated with \0. Returns s if successful. If EOF is encountered before any characters are read, the contents of s are unchanged, and NULL is returned. If a read error occurs, the contents of s are indeter- minate, and NULL is returned. + + This function is dangerous and has been a great source of security + vulnerabilities. Do not use it. It was removed by C11. */ -char * gets( char * s ) _PDCLIB_nothrow; +char * gets( char * s ) _PDCLIB_DEPRECATED _PDCLIB_nothrow; +#endif /* Equivalent to fputc( c, stream ), but may be overloaded by a macro that evaluates its parameter more than once. diff --git a/internals/_PDCLIB_aux.h b/internals/_PDCLIB_aux.h index 0844962..986807e 100644 --- a/internals/_PDCLIB_aux.h +++ b/internals/_PDCLIB_aux.h @@ -23,28 +23,28 @@ #endif #if defined(_PDCLIB_C_VERSION) - /* Pass - conditional simplification case */ + /* Pass - conditional simplification case */ #elif !defined(__STDC_VERSION__) - #define _PDCLIB_C_VERSION 1990 + #define _PDCLIB_C_VERSION 1990 #elif __STDC_VERSION__ == 199409L - #define _PDCLIB_C_VERSION 1995 + #define _PDCLIB_C_VERSION 1995 #elif __STDC_VERSION__ == 199901L - #define _PDCLIB_C_VERSION 1999 + #define _PDCLIB_C_VERSION 1999 #elif __STDC_VERSION__ == 201112L - #define _PDCLIB_C_VERSION 2011 + #define _PDCLIB_C_VERSION 2011 #else - #error Unsupported _ _STDC_VERSION_ _ (__STDC_VERSION__) (supported: ISO/IEC 9899:1990, 9899/AMD1:1995, 9899:1999, 9899:2011). + #error Unsupported _ _STDC_VERSION_ _ (__STDC_VERSION__) (supported: ISO/IEC 9899:1990, 9899/AMD1:1995, 9899:1999, 9899:2011). #endif #if !defined(__cplusplus) || defined(_PDCLIB_CXX_VERSION) #define _PDCLIB_CXX_VERSION 0 #elif __cplusplus == 201103L - #define _PDCLIB_CXX_VERSION 2011 + #define _PDCLIB_CXX_VERSION 2011 /* TODO: Do we want this? */ - #if _PDCLIB_C_VERSION < 2011 - #undef _PDCLIB_C_VERSION - #define _PDCLIB_C_VERSION 2011 - #endif + #if _PDCLIB_C_VERSION < 2011 + #undef _PDCLIB_C_VERSION + #define _PDCLIB_C_VERSION 2011 + #endif #elif __cplusplus == 199711L #define _PDCLIB_CXX_VERSION 1997 #else @@ -52,10 +52,10 @@ #endif #if _PDCLIB_C_VERSION >= 1999 || defined(__cplusplus) - #ifndef __cplusplus - #define _PDCLIB_restrict restrict - #endif - #define _PDCLIB_inline inline + #ifndef __cplusplus + #define _PDCLIB_restrict restrict + #endif + #define _PDCLIB_inline inline #endif #if _PDCLIB_CXX_VERSION >= 2011 @@ -70,7 +70,7 @@ // Hold off on C++ attribute syntax for now // #define _PDCLIB_noreturn [[noreturn]] #elif _PDCLIB_C_VERSION >= 2011 - #define _PDCLIB_noreturn _Noreturn + #define _PDCLIB_noreturn _Noreturn #endif #ifdef _WIN32 @@ -79,35 +79,39 @@ #endif #ifdef __GNUC__ - #ifndef _PDCLIB_EXPORT - #define _PDCLIB_EXPORT __attribute__((__visibility__("protected"))) + #ifndef _PDCLIB_EXPORT + #define _PDCLIB_EXPORT __attribute__((__visibility__("protected"))) #endif - #ifndef _PDCLIB_IMPORT - #define _PDCLIB_IMPORT - #endif + #ifndef _PDCLIB_IMPORT + #define _PDCLIB_IMPORT + #endif - #ifndef _PDCLIB_HIDDEN - #define _PDCLIB_HIDDEN __attribute__((__visibility__("hidden"))) - #endif + #ifndef _PDCLIB_HIDDEN + #define _PDCLIB_HIDDEN __attribute__((__visibility__("hidden"))) + #endif #ifndef _PDCLIB_nothrow #define _PDCLIB_nothrow __attribute__((__nothrow__)) #define _PDCLIB_noexcept #endif - #ifndef _PDCLIB_restrict - #define _PDCLIB_restrict __restrict - #endif + #ifndef _PDCLIB_restrict + #define _PDCLIB_restrict __restrict + #endif - #ifndef _PDCLIB_inline - #define _PDCLIB_inline __inline - #endif + #ifndef _PDCLIB_inline + #define _PDCLIB_inline __inline + #endif - #ifndef _PDCLIB_noreturn + #ifndef _PDCLIB_noreturn /* If you don't use __noreturn__, then stdnoreturn.h will break things! */ - #define _PDCLIB_noreturn __attribute__((__noreturn__)) - #endif + #define _PDCLIB_noreturn __attribute__((__noreturn__)) + #endif + + #ifndef _PDCLIB_DEPRECATED + #define _PDCLIB_DEPRECATED __attribute__ ((deprecated)) + #endif #endif #ifndef _PDCLIB_nothrow @@ -116,35 +120,39 @@ #endif #ifndef _PDCLIB_EXPORT - #define _PDCLIB_EXPORT + #define _PDCLIB_EXPORT #endif #ifndef _PDCLIB_IMPORT - #define _PDCLIB_IMPORT + #define _PDCLIB_IMPORT #endif #ifndef _PDCLIB_HIDDEN - #define _PDCLIB_HIDDEN + #define _PDCLIB_HIDDEN #endif #if defined(_PDCLIB_SHARED) - #if defined(_PDCLIB_BUILD) - #define _PDCLIB_API _PDCLIB_EXPORT - #else - #define _PDCLIB_API _PDCLIB_IMPORT - #endif + #if defined(_PDCLIB_BUILD) + #define _PDCLIB_API _PDCLIB_EXPORT + #else + #define _PDCLIB_API _PDCLIB_IMPORT + #endif #else - #define _PDCLIB_API + #define _PDCLIB_API #endif #ifndef _PDCLIB_restrict - #define _PDCLIB_restrict + #define _PDCLIB_restrict #endif #ifndef _PDCLIB_inline - #define _PDCLIB_inline + #define _PDCLIB_inline #endif #ifndef _PDCLIB_noreturn - #define _PDCLIB_noreturn + #define _PDCLIB_noreturn +#endif + +#ifndef _PDCLIB_DEPRECATED + #define _PDCLIB_DEPRECATED #endif #ifndef __STDC_HOSTED__ @@ -158,8 +166,8 @@ #endif #ifdef __cplusplus - #define _PDCLIB_BEGIN_EXTERN_C extern "C" { - #define _PDCLIB_END_EXTERN_C } + #define _PDCLIB_BEGIN_EXTERN_C extern "C" { + #define _PDCLIB_END_EXTERN_C } typedef bool _PDCLIB_bool; #else #define _PDCLIB_BEGIN_EXTERN_C @@ -187,9 +195,9 @@ /* Feature test macros * * All of the feature test macros come in the following forms - * _PDCLIB_*_MIN(min): Available in versions > min - * _PDCLIB_*_MINMAX(min, max): Available in versions > min < max - * _PDCLIB_*_MAX(max): Availabel in versions < max + * _PDCLIB_*_MIN(min): Available in versions >= min + * _PDCLIB_*_MINMAX(min, max): Available in versions >= min <= max + * _PDCLIB_*_MAX(max): Availabel in versions <= max * * The defined tests are: * C: C standard versions -- 2.40.0 From e6d28b5afddd8b3e3564af2264aa8b705e711b67 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Tue, 11 Dec 2012 01:42:35 +0000 Subject: [PATCH 08/16] PDCLIB-18: Add _PDCLIB_getchars to _PDCLIB_io.h. Change fread & fgets to go through this function. All narrow character reads are going to be directed through this function --- functions/stdio/fgets.c | 17 +++-------------- functions/stdio/fread.c | 16 ++++------------ functions/stdio/ungetc.c | 1 + internals/_PDCLIB_io.h | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/functions/stdio/fgets.c b/functions/stdio/fgets.c index 0451058..6fbc2ef 100644 --- a/functions/stdio/fgets.c +++ b/functions/stdio/fgets.c @@ -28,20 +28,9 @@ char * fgets_unlocked( char * _PDCLIB_restrict s, int size, struct _PDCLIB_file_ return NULL; } char * dest = s; - while ( ( ( *dest++ = stream->buffer[stream->bufidx++] ) != '\n' ) && --size > 0 ) - { - if ( stream->bufidx == stream->bufend ) - { - if ( _PDCLIB_fillbuffer( stream ) == EOF ) - { - /* In case of error / EOF before a character is read, this - will lead to a \0 be written anyway. Since the results - are "indeterminate" by definition, this does not hurt. - */ - break; - } - } - } + + dest += _PDCLIB_getchars( dest, size - 1, '\n', stream ); + *dest = '\0'; return ( dest == s ) ? NULL : s; } diff --git a/functions/stdio/fread.c b/functions/stdio/fread.c index 1fdc753..f1ab3a9 100644 --- a/functions/stdio/fread.c +++ b/functions/stdio/fread.c @@ -27,18 +27,10 @@ size_t fread_unlocked( void * _PDCLIB_restrict ptr, size_t nmemb_i; for ( nmemb_i = 0; nmemb_i < nmemb; ++nmemb_i ) { - for ( size_t size_i = 0; size_i < size; ++size_i ) - { - if ( stream->bufidx == stream->bufend ) - { - if ( _PDCLIB_fillbuffer( stream ) == EOF ) - { - /* Could not read requested data */ - return nmemb_i; - } - } - dest[ nmemb_i * size + size_i ] = stream->buffer[ stream->bufidx++ ]; - } + size_t numread = _PDCLIB_getchars( &dest[ nmemb_i * size ], size, EOF, + stream ); + if( numread != size ) + break; } return nmemb_i; } diff --git a/functions/stdio/ungetc.c b/functions/stdio/ungetc.c index 2e556ab..4e9388b 100644 --- a/functions/stdio/ungetc.c +++ b/functions/stdio/ungetc.c @@ -31,6 +31,7 @@ int ungetc( int c, struct _PDCLIB_file_t * stream ) #ifdef TEST #include <_PDCLIB_test.h> +#include const char* hellostr = "Hello, world!"; diff --git a/internals/_PDCLIB_io.h b/internals/_PDCLIB_io.h index 829bb45..2ece56c 100644 --- a/internals/_PDCLIB_io.h +++ b/internals/_PDCLIB_io.h @@ -151,5 +151,40 @@ struct _PDCLIB_file_t struct _PDCLIB_file_t * next; /* Pointer to next struct (internal) */ }; +static inline _PDCLIB_size_t _PDCLIB_getchars( char * out, _PDCLIB_size_t n, + int stopchar, + struct _PDCLIB_file_t * stream ) +{ + _PDCLIB_size_t i = 0; + int c; + while ( stream->ungetidx > 0 && i != n ) + { + c = (unsigned char) + ( out[ i++ ] = stream->ungetbuf[ --(stream->ungetidx) ] ); + if( c == stopchar ) + return i; + } + + while ( i != n ) + { + while ( stream->bufidx != stream->bufend && i != n) + { + c = (unsigned char) + ( out[ i++ ] = stream->buffer[ stream->bufidx++ ] ); + if( c == stopchar ) + return i; + } + + if ( stream->bufidx == stream->bufend ) + { + if( _PDCLIB_fillbuffer( stream ) == -1 ) + { + return i; + } + } + } + + return i; +} #endif -- 2.40.0 From b852731d2bc40ce2208264cdb55cc8e27944c890 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Tue, 11 Dec 2012 02:00:22 +0000 Subject: [PATCH 09/16] PDCLIB-18: Unify fgetc under _PDCLIB_getchars. Also unify gets under _PDCLIB_getchars (gets also suffered from the bug) --- functions/stdio/fgetc.c | 11 ++++++----- functions/stdio/gets.c | 20 +++++++++----------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/functions/stdio/fgetc.c b/functions/stdio/fgetc.c index ae7a835..61f52fd 100644 --- a/functions/stdio/fgetc.c +++ b/functions/stdio/fgetc.c @@ -18,11 +18,12 @@ int fgetc_unlocked( struct _PDCLIB_file_t * stream ) { return EOF; } - if ( stream->ungetidx > 0 ) - { - return (unsigned char)stream->ungetbuf[ --(stream->ungetidx) ]; - } - return (unsigned char)stream->buffer[stream->bufidx++]; + + char c; + + size_t n = _PDCLIB_getchars( &c, 1, EOF, stream ); + + return n == 0 ? EOF : (unsigned char) c; } int fgetc( struct _PDCLIB_file_t * stream ) diff --git a/functions/stdio/gets.c b/functions/stdio/gets.c index 9bf3a26..3185396 100644 --- a/functions/stdio/gets.c +++ b/functions/stdio/gets.c @@ -10,6 +10,7 @@ #ifndef REGTEST #include <_PDCLIB_glue.h> +#include char * gets( char * s ) { @@ -18,18 +19,15 @@ char * gets( char * s ) return NULL; } char * dest = s; - while ( ( *dest = stdin->buffer[stdin->bufidx++] ) != '\n' ) - { - ++dest; - if ( stdin->bufidx == stdin->bufend ) - { - if ( _PDCLIB_fillbuffer( stdin ) == EOF ) - { - break; - } - } + + dest += _PDCLIB_getchars( dest, SIZE_MAX, '\n', stdin ); + + if(*(dest - 1) == '\n') { + *(--dest) = '\0'; + } else { + *dest = '\0'; } - *dest = '\0'; + return ( dest == s ) ? NULL : s; } -- 2.40.0 From 25444caf1a2d59e4a2fc8d1058fb0f0a4b9ff731 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Fri, 14 Dec 2012 15:36:25 +0000 Subject: [PATCH 10/16] Add Sublime Text project file --- pdclib.sublime-project | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 pdclib.sublime-project diff --git a/pdclib.sublime-project b/pdclib.sublime-project new file mode 100644 index 0000000..483ab57 --- /dev/null +++ b/pdclib.sublime-project @@ -0,0 +1,44 @@ +{ + "folders": + [ + { + "name": "PDCLib", + "path": ".", + "file_exclude_patterns": ["*.o", "*_t", "*_r", "*.exe"] + } + ], + + "settings": + { + "tab_size": 4, + "translate_tabs_to_spaces": true, + "rulers": [ 80 ], + "use_tab_stops": true + }, + + "build_systems": + [ + { + "name": "PDCLib Jam", + "working_dir": "$project_path", + "cmd": ["jam", "-qj4"], + + "variants": [ + { + "cmd": ["jam", "test"], + "name": "Run" + }, + { + "cmd": ["jam", "regtest"], + "name": "Regtest" + } + ], + + "windows": { + "env": { + "JAM_TOOLSET": "MINGW" + } + } + } + ] +} -- 2.40.0 From b43055b06b74c0a45128531e4f18bef0c5a49efc Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Wed, 26 Dec 2012 18:50:04 +0000 Subject: [PATCH 11/16] _PDCLIB_scan: Had incorrect upper bound on field width causing integer overflow --- functions/_PDCLIB/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/_PDCLIB/scan.c b/functions/_PDCLIB/scan.c index 57f9831..7e6c42c 100644 --- a/functions/_PDCLIB/scan.c +++ b/functions/_PDCLIB/scan.c @@ -162,7 +162,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ) status->width = (int)strtol( spec, (char**)&spec, 10 ); if ( spec == prev_spec ) { - status->width = SIZE_MAX; + status->width = INT_MAX; } /* Optional length modifier -- 2.40.0 From a4b64221a092c3956abf5d00592bdd5ade189f90 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Wed, 26 Dec 2012 18:50:48 +0000 Subject: [PATCH 12/16] _PDCLIB_seek: Incorrect specification (used int64_t where int_fast64_t was correct) --- functions/stdio/_PDCLIB_seek.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/functions/stdio/_PDCLIB_seek.c b/functions/stdio/_PDCLIB_seek.c index 5a3f982..42c3273 100644 --- a/functions/stdio/_PDCLIB_seek.c +++ b/functions/stdio/_PDCLIB_seek.c @@ -9,7 +9,8 @@ #include #ifndef REGTEST -int_fast64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int64_t offset, +int_fast64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, + int_fast64_t offset, int whence ) { int_fast64_t newPos; -- 2.40.0 From 28f6edc984f962ed33ac4fb505cf94b3e78f3f6d Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Wed, 26 Dec 2012 18:51:35 +0000 Subject: [PATCH 13/16] _PDCLIB_aux.h: Better detection of Clang and GCC features --- internals/_PDCLIB_aux.h | 151 ++++++++++++++++++++++++++-------------- 1 file changed, 100 insertions(+), 51 deletions(-) diff --git a/internals/_PDCLIB_aux.h b/internals/_PDCLIB_aux.h index 986807e..bc13897 100644 --- a/internals/_PDCLIB_aux.h +++ b/internals/_PDCLIB_aux.h @@ -51,6 +51,80 @@ #error Unsupported _ _cplusplus (__cplusplus) (supported: ISO/IEC 14882:1997, ISO/IEC 14882:2011). #endif +#ifndef __STDC_HOSTED__ + #error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)! +#elif __STDC_HOSTED__ == 0 + #define _PDCLIB_HOSTED 0 +#elif __STDC_HOSTED__ == 1 + #define _PDCLIB_HOSTED 1 +#else + #error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)! +#endif + +#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 + typedef _Bool _PDCLIB_bool; +#endif + +/* Clang style feature detection macros + * Note: It is common to #define __has_feature(0) if undefined so the presence + * of this macro does not guarantee it to be working + */ + +#ifdef __has_feature + #define _PDCLIB_HAS_FEATURE(x) __has_feature(x) +#else + #define _PDCLIB_HAS_FEATURE(x) (0) +#endif + +#ifdef __has_extension + #define _PDCLIB_HAS_EXTENSION(x) __has_extension(x) +#else + // Older versions of Clang use __has_feature instead + #define _PDCLIB_HAS_EXTENSION(x) _PDCLIB_HAS_FEATURE(x) +#endif + +#ifdef __has_builtin + #define _PDCLIB_HAS_BUILTIN(x) __has_builtin(x) +#else + #define _PDCLIB_HAS_BUILTIN(x) (0) +#endif + +#ifdef __has_attribute + #define _PDCLIB_HAS_ATTRIBUTE(x) __has_builtin(x) +#else + #define _PDCLIB_HAS_ATTRIBUTE(x) (0) +#endif + +/* GCC feature detection macros */ + +#if defined(__GNUC__) + #define _PDCLIB_GCC_MIN(maj, min) \ + ((__GNUC__ > maj) || (__GNUC__ == maj && __GNUC_MINOR__ >= min)) +#else + #define _PDCLIB_GCC_MIN(maj, min) (0) +#endif + +/* Hybrid GCC/Clang feature detection macros */ +#define _PDCLIB_GCC_FEATURE(x, gccmaj, gccmin) \ + (_PDCLIB_HAS_FEATURE(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj)) + +#define _PDCLIB_GCC_EXTENSION(x, gccmaj, gccmin) \ + (_PDCLIB_HAS_EXTENSION(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj)) + +#define _PDCLIB_GCC_BUILTIN(x, gccmaj, gccmin) \ + (_PDCLIB_HAS_BUILTIN(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj)) + +#define _PDCLIB_GCC_ATTRIBUTE(x, gccmaj, gccmin) \ + (_PDCLIB_HAS_ATTRIBUTE(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj)) + +/* Extension & Language feature detection */ + #if _PDCLIB_C_VERSION >= 1999 || defined(__cplusplus) #ifndef __cplusplus #define _PDCLIB_restrict restrict @@ -66,10 +140,9 @@ #define _PDCLIB_noexcept #endif -#if _PDCLIB_CXX_VERSION >= 2011 - // Hold off on C++ attribute syntax for now - // #define _PDCLIB_noreturn [[noreturn]] -#elif _PDCLIB_C_VERSION >= 2011 +#if _PDCLIB_CXX_VERSION >= 2011 && _PDCLIB_GCC_FEATURE(cxx_attributes, 4, 8) + #define _PDCLIB_noreturn [[noreturn]] +#elif _PDCLIB_C_VERSION >= 2011 && _PDCLIB_GCC_FEATURE(c_noreturn, 4, 7) #define _PDCLIB_noreturn _Noreturn #endif @@ -78,42 +151,38 @@ #define _PDCLIB_IMPORT __declspec(dllimport) #endif -#ifdef __GNUC__ - #ifndef _PDCLIB_EXPORT - #define _PDCLIB_EXPORT __attribute__((__visibility__("protected"))) - #endif - - #ifndef _PDCLIB_IMPORT - #define _PDCLIB_IMPORT - #endif +#if !defined(_PDCLIB_EXPORT) && _PDCLIB_GCC_ATTRIBUTE(__visibility__, 4, 0) + #define _PDCLIB_EXPORT __attribute__((__visibility__("protected"))) +#endif - #ifndef _PDCLIB_HIDDEN - #define _PDCLIB_HIDDEN __attribute__((__visibility__("hidden"))) - #endif +#if !defined(_PDCLIB_HIDDEN) && _PDCLIB_GCC_ATTRIBUTE(__visibility__, 4, 0) + #define _PDCLIB_HIDDEN __attribute__((__visibility__("hidden"))) +#endif - #ifndef _PDCLIB_nothrow - #define _PDCLIB_nothrow __attribute__((__nothrow__)) - #define _PDCLIB_noexcept - #endif +#if !defined(_PDCLIB_nothrow) && _PDCLIB_GCC_ATTRIBUTE(__nothrow__, 4, 0) + #define _PDCLIB_nothrow __attribute__((__nothrow__)) + #define _PDCLIB_noexcept +#endif - #ifndef _PDCLIB_restrict - #define _PDCLIB_restrict __restrict - #endif +#if !defined(_PDCLIB_restrict) && _PDCLIB_GCC_MIN(3, 0) + #define _PDCLIB_restrict __restrict +#endif - #ifndef _PDCLIB_inline - #define _PDCLIB_inline __inline - #endif +#if !defined(_PDCLIB_inline) && _PDCLIB_GCC_MIN(3, 0) + #define _PDCLIB_inline __inline +#endif - #ifndef _PDCLIB_noreturn +#if !defined(_PDCLIB_noreturn) && _PDCLIB_GCC_ATTRIBUTE(__noreturn__, 3, 0) /* If you don't use __noreturn__, then stdnoreturn.h will break things! */ - #define _PDCLIB_noreturn __attribute__((__noreturn__)) - #endif + #define _PDCLIB_noreturn __attribute__((__noreturn__)) +#endif - #ifndef _PDCLIB_DEPRECATED - #define _PDCLIB_DEPRECATED __attribute__ ((deprecated)) - #endif +#if !defined(_PDCLIB_DEPRECATED) && _PDCLIB_GCC_ATTRIBUTE(__deprecated__, 3, 0) + #define _PDCLIB_DEPRECATED __attribute__ ((__deprecated__)) #endif +/* No-op fallbacks */ + #ifndef _PDCLIB_nothrow #define _PDCLIB_nothrow #define _PDCLIB_noexcept @@ -155,26 +224,6 @@ #define _PDCLIB_DEPRECATED #endif -#ifndef __STDC_HOSTED__ -#error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)! -#elif __STDC_HOSTED__ == 0 -#define _PDCLIB_HOSTED 0 -#elif __STDC_HOSTED__ == 1 -#define _PDCLIB_HOSTED 1 -#else -#error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)! -#endif - -#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 - typedef _Bool _PDCLIB_bool; -#endif - /*#if _PDCLIB_C_VERSION != 1999 #error PDCLib might not be fully conforming to either C89 or C95 prior to v2.x. #endif*/ -- 2.40.0 From 0bd5eb227b6f2d515b90fe88087f58ed74286348 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Wed, 26 Dec 2012 18:53:47 +0000 Subject: [PATCH 14/16] win32: _PDCLIB_config.h cleaned up: * _PDCLIB_NOHANDLE removed (obsolete) * _PDCLIB_NORETURN removed (obsolete) * Temp name length was greated than max guaranteed file name length. This has obvious issus. --- platform/win32/internals/_PDCLIB_config.h | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/platform/win32/internals/_PDCLIB_config.h b/platform/win32/internals/_PDCLIB_config.h index 57a2d29..5e91db5 100644 --- a/platform/win32/internals/_PDCLIB_config.h +++ b/platform/win32/internals/_PDCLIB_config.h @@ -27,12 +27,6 @@ /* specific platforms, e.g. by swapping int instead of char. */ #define _PDCLIB_memswp( i, j, size ) char tmp; do { tmp = *i; *i++ = *j; *j++ = tmp; } while ( --size ); -/* Define this to some compiler directive that can be written after the */ -/* parameter list of a function declaration to indicate the function does */ -/* never return. If your compiler does not support such a directive, define */ -/* to nothing. (This is to avoid warnings with the exit functions under GCC.) */ -#define _PDCLIB_NORETURN __attribute__(( noreturn )) - /* The maximum value that errno can be set to. This is used to set the size */ /* of the array in struct lconv () holding error messages for the */ /* strerror() and perror() functions. (If you change this value because you */ @@ -341,11 +335,6 @@ struct _PDCLIB_imaxdiv_t /* I/O ---------------------------------------------------------------------- */ -/* The value (of type _PDCLIB_fd_t) returned by _PDCLIB_open() if the operation - failed. -*/ -#define _PDCLIB_NOHANDLE NULL - /* The default size for file buffers. Must be at least 256. */ #define _PDCLIB_BUFSIZ 1024 @@ -357,7 +346,7 @@ struct _PDCLIB_imaxdiv_t #define _PDCLIB_FOPEN_MAX 8 /* Length of the longest filename the implementation guarantees to support. */ -#define _PDCLIB_FILENAME_MAX 128 +#define _PDCLIB_FILENAME_MAX 260 /* Maximum length of filenames generated by tmpnam(). (See tmpfile.c.) */ #define _PDCLIB_L_tmpnam 260 -- 2.40.0 From 86e885d620860db125684fb0ab4d084891227a62 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Wed, 26 Dec 2012 18:54:57 +0000 Subject: [PATCH 15/16] posix: First pass at updated config file for POSIX platforms --- platform/posix/internals/_PDCLIB_config.h | 113 ++++++++++++++-------- 1 file changed, 74 insertions(+), 39 deletions(-) diff --git a/platform/posix/internals/_PDCLIB_config.h b/platform/posix/internals/_PDCLIB_config.h index 4252cff..314eed5 100644 --- a/platform/posix/internals/_PDCLIB_config.h +++ b/platform/posix/internals/_PDCLIB_config.h @@ -2,7 +2,7 @@ #define _PDCLIB_CONFIG_H /* Internal PDCLib configuration <_PDCLIB_config.h> - (Generic Template) + (POSIX platform) This file is part of the Public Domain C Library (PDCLib). Permission is granted to use, modify, and / or redistribute at will. @@ -55,7 +55,11 @@ /* compiler manuals. */ #define _PDCLIB_SHRT_BYTES 2 #define _PDCLIB_INT_BYTES 4 -#define _PDCLIB_LONG_BYTES 4 +#if defined(_LP64) || defined(__ILP64__) + #define _PDCLIB_LONG_BYTES 8 +#else + #define _PDCLIB_LONG_BYTES 4 +#endif #define _PDCLIB_LLONG_BYTES 8 /* defines the div() function family that allows taking quotient */ @@ -125,9 +129,9 @@ struct _PDCLIB_lldiv_t /* -------------------------------------------------------------------------- */ /* The result type of substracting two pointers */ -#define _PDCLIB_ptrdiff int -#define _PDCLIB_PTRDIFF INT -#define _PDCLIB_PTR_CONV +#define _PDCLIB_ptrdiff long +#define _PDCLIB_PTRDIFF LONG +#define _PDCLIB_PTR_CONV l /* An integer type that can be accessed as atomic entity (think asynchronous interrupts). The type itself is not defined in a freestanding environment, @@ -137,17 +141,18 @@ struct _PDCLIB_lldiv_t #define _PDCLIB_SIG_ATOMIC INT /* Result type of the 'sizeof' operator (must be unsigned) */ -#define _PDCLIB_size unsigned int -#define _PDCLIB_SIZE UINT +#define _PDCLIB_size unsigned long +#define _PDCLIB_SIZE ULONG /* Large enough an integer to hold all character codes of the largest supported locale. */ -#define _PDCLIB_wchar unsigned short -#define _PDCLIB_WCHAR USHRT +#define _PDCLIB_wint signed int +#define _PDCLIB_wchar unsigned int +#define _PDCLIB_WCHAR UINT -#define _PDCLIB_intptr int -#define _PDCLIB_INTPTR INT +#define _PDCLIB_intptr long +#define _PDCLIB_INTPTR LONG /* Largest supported integer type. Implementation note: see _PDCLIB_atomax(). */ #define _PDCLIB_intmax long long int @@ -192,9 +197,22 @@ struct _PDCLIB_imaxdiv_t * * On XSI systems, CLOCKS_PER_SEC must be defined to 1000000 */ -#define _PDCLIB_clock double +#define _PDCLIB_clock long #define _PDCLIB_CLOCKS_PER_SEC 1000000 +/* : TIME_UTC + * + * The TIME_UTC parameter is passed to the timespec_get function in order to get + * the system time in UTC since an implementation defined epoch (not necessarily + * the same as that used for time_t). That said, on POSIX the obvious + * implementation of timespec_get for TIME_UTC is to wrap + * clock_gettime(CLOCK_REALTIME, ...), which is defined as time in UTC since the + * same epoch. + * + * This may be any non-zero integer value. + */ +#define _PDCLIB_TIME_UTC 1 + /* -------------------------------------------------------------------------- */ /* Floating Point */ /* -------------------------------------------------------------------------- */ @@ -222,6 +240,18 @@ struct _PDCLIB_imaxdiv_t */ #define _PDCLIB_DECIMAL_DIG 17 +/* Floating point types + * + * PDCLib (at present) assumes IEEE 754 floating point formats + * The following names are used: + * SINGLE: IEEE 754 single precision (32-bit) + * DOUBLE: IEEE 754 double precision (64-bit) + * EXTENDED: IEEE 754 extended precision (80-bit, as x87) + */ +#define _PDCLIB_FLOAT_TYPE SINGLE +#define _PDCLIB_DOUBLE_TYPE DOUBLE +#define _PDCLIB_LDOUBLE_TYPE EXTENDED + /* -------------------------------------------------------------------------- */ /* Platform-dependent macros defined by the standard headers. */ /* -------------------------------------------------------------------------- */ @@ -236,24 +266,36 @@ struct _PDCLIB_imaxdiv_t takes the address of member. This is undefined behaviour but should work on most compilers. */ -#define _PDCLIB_offsetof( type, member ) ( (size_t) &( ( (type *) 0 )->member ) ) +#ifdef __GNUC__ + #define _PDCLIB_offsetof( type, member ) __builtin_offsetof( type, member ) +#else + #define _PDCLIB_offsetof( type, member ) ( (size_t) &( ( (type *) 0 )->member ) ) +#endif /* Variable Length Parameter List Handling () The macros defined by are highly dependent on the calling conventions used, and you probably have to replace them with builtins of - your compiler. The following generic implementation works only for pure - stack-based architectures, and only if arguments are aligned to pointer - type. Credits to Michael Moody, who contributed this to the Public Domain. + your compiler. */ -/* Internal helper macro. va_round is not part of . */ -#define _PDCLIB_va_round( type ) ( (sizeof(type) + sizeof(void *) - 1) & ~(sizeof(void *) - 1) ) - -typedef char * _PDCLIB_va_list; -#define _PDCLIB_va_arg( ap, type ) ( (ap) += (_PDCLIB_va_round(type)), ( *(type*) ( (ap) - (_PDCLIB_va_round(type)) ) ) ) -#define _PDCLIB_va_copy( dest, src ) ( (dest) = (src), (void)0 ) -#define _PDCLIB_va_end( ap ) ( (ap) = (void *)0, (void)0 ) -#define _PDCLIB_va_start( ap, parmN ) ( (ap) = (char *) &parmN + ( _PDCLIB_va_round(parmN) ), (void)0 ) +#ifdef __GNUC__ + typedef __builtin_va_list _PDCLIB_va_list; + #define _PDCLIB_va_arg( ap, type ) (__builtin_va_arg( (ap), type )) + #define _PDCLIB_va_copy( dest, src ) (__builtin_va_copy( (dest), (src) )) + #define _PDCLIB_va_end( ap ) (__builtin_va_end( ap ) ) + #define _PDCLIB_va_start( ap, parmN ) (__builtin_va_start( (ap), (parmN) )) +#elif (defined(__i386__) || defined(__i386) || defined(_M_IX86)) && !(defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)) + /* Internal helper macro. va_round is not part of . */ + #define _PDCLIB_va_round( type ) ( (sizeof(type) + sizeof(void *) - 1) & ~(sizeof(void *) - 1) ) + + typedef char * _PDCLIB_va_list; + #define _PDCLIB_va_arg( ap, type ) ( (ap) += (_PDCLIB_va_round(type)), ( *(type*) ( (ap) - (_PDCLIB_va_round(type)) ) ) ) + #define _PDCLIB_va_copy( dest, src ) ( (dest) = (src), (void)0 ) + #define _PDCLIB_va_end( ap ) ( (ap) = (void *)0, (void)0 ) + #define _PDCLIB_va_start( ap, parmN ) ( (ap) = (char *) &parmN + ( _PDCLIB_va_round(parmN) ), (void)0 ) +#else + #error Compiler/Architecture support please +#endif /* -------------------------------------------------------------------------- */ /* OS "glue", part 1 */ @@ -268,24 +310,17 @@ typedef char * _PDCLIB_va_list; to an appropriate value. (Too small, and malloc() will call the kernel too often. Too large, and you will waste memory.) */ -#define _PDCLIB_PAGESIZE 4096 +#define _PDCLIB_MALLOC_PAGESIZE 4096 +#define _PDCLIB_MALLOC_ALIGN 16 +#define _PDCLIB_MALLOC_GRANULARITY 64*1024 +#define _PDCLIB_MALLOC_TRIM_THRESHOLD 2*1024*1024 +#define _PDCLIB_MALLOC_MMAP_THRESHOLD 256*1024 +#define _PDCLIB_MALLOC_RELEASE_CHECK_RATE 4095 -/* Set this to the minimum memory node size. Any malloc() for a smaller size - will be satisfied by a malloc() of this size instead (to avoid excessive - fragmentation). -*/ -#define _PDCLIB_MINALLOC 8 +/* TODO: Better document these */ /* I/O ---------------------------------------------------------------------- */ -/* The type of the file descriptor returned by _PDCLIB_open(). */ -typedef int _PDCLIB_fd_t; - -/* The value (of type _PDCLIB_fd_t) returned by _PDCLIB_open() if the operation - failed. -*/ -#define _PDCLIB_NOHANDLE ( (_PDCLIB_fd_t) -1 ) - /* The default size for file buffers. Must be at least 256. */ #define _PDCLIB_BUFSIZ 1024 @@ -300,7 +335,7 @@ typedef int _PDCLIB_fd_t; #define _PDCLIB_FILENAME_MAX 128 /* Maximum length of filenames generated by tmpnam(). (See tmpfile.c.) */ -#define _PDCLIB_L_tmpnam 46 +#define _PDCLIB_L_tmpnam 128 /* Number of distinct file names that can be generated by tmpnam(). */ #define _PDCLIB_TMP_MAX 50 -- 2.40.0 From 0cf5cdb61dae0e9ce894115ef69b79d8b2507d54 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Wed, 26 Dec 2012 19:45:24 +0000 Subject: [PATCH 16/16] _PDCLIB_scan: Correct INT_MAX -> UINT_MAX when initializing width vfprintf: Correct SIZE_MAX -> UINT_MAX when initializing width --- functions/_PDCLIB/scan.c | 2 +- functions/stdio/vfprintf.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/functions/_PDCLIB/scan.c b/functions/_PDCLIB/scan.c index 7e6c42c..0ecf31a 100644 --- a/functions/_PDCLIB/scan.c +++ b/functions/_PDCLIB/scan.c @@ -162,7 +162,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ) status->width = (int)strtol( spec, (char**)&spec, 10 ); if ( spec == prev_spec ) { - status->width = INT_MAX; + status->width = UINT_MAX; } /* Optional length modifier diff --git a/functions/stdio/vfprintf.c b/functions/stdio/vfprintf.c index ffb4bbe..18e9c4b 100644 --- a/functions/stdio/vfprintf.c +++ b/functions/stdio/vfprintf.c @@ -9,6 +9,7 @@ #include #include #include +#include #ifndef REGTEST @@ -20,7 +21,7 @@ int vfprintf_unlocked( struct _PDCLIB_file_t * _PDCLIB_restrict stream, struct _PDCLIB_status_t status; status.base = 0; status.flags = 0; - status.n = SIZE_MAX; + status.n = UINT_MAX; status.i = 0; status.current = 0; status.s = NULL; -- 2.40.0