PDCLIB-15: Make most stdio routines lock the stream and then call through to the _unlocked version
#ifndef REGTEST\r
#include <_PDCLIB_glue.h>\r
#include <string.h>\r
+#include <threads.h>\r
\r
extern struct _PDCLIB_file_t * _PDCLIB_filelist;\r
\r
\r
#ifndef REGTEST\r
\r
-uint_fast64_t _PDCLIB_ftell64( struct _PDCLIB_file_t * stream )\r
+uint_fast64_t _PDCLIB_ftell64_unlocked( struct _PDCLIB_file_t * stream )\r
{\r
/* ftell() must take into account:\r
- the actual *physical* offset of the file, i.e. the offset as recognized\r
return ( stream->pos.offset - ( ( (int)stream->bufend - (int)stream->bufidx ) + (int)stream->ungetidx ) );\r
}\r
\r
+uint_fast64_t _PDCLIB_ftell64( struct _PDCLIB_file_t * stream )\r
+{\r
+ flockfile( stream );\r
+ uint_fast64_t pos = _PDCLIB_ftell64_unlocked( stream );\r
+ funlockfile( stream );\r
+ return pos;\r
+}\r
+\r
#endif\r
\r
#ifdef TEST\r
#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
#ifndef REGTEST
#include <_PDCLIB_glue.h>
+#include <threads.h>
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
#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
#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
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 )
{
return _PDCLIB_flushbuffer( stream );
}
}
+
+int fflush( struct _PDCLIB_file_t * stream )
+{
+ flockfile( stream );
+ int res = fflush_unlocked(stream);
+ funlockfile( stream );
+ return res;
+}
#endif
#include <_PDCLIB_glue.h>
-int fgetc( struct _PDCLIB_file_t * stream )
+int fgetc_unlocked( struct _PDCLIB_file_t * stream )
{
if ( _PDCLIB_prepread( stream ) == EOF )
{
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
#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;
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
#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 )
{
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
#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;
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
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 )
{
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
#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 )
{
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>
#include <stdbool.h>
#include <string.h>
-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 )
{
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
#include <stdlib.h>
#include <string.h>
-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 )
if ( ( filename == NULL ) && ( stream->filename == NULL ) )
{
/* TODO: Special handling for mode changes on std-streams */
+ funlockfile( stream );
return NULL;
}
_PDCLIB_close( stream->handle );
/* 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 */
/* TODO: Setting mbstate */
if ( ( stream->handle = _PDCLIB_open( filename, stream->status ) ) == _PDCLIB_NOHANDLE )
{
+ funlockfile( stream );
return NULL;
}
+ funlockfile( stream );
return stream;
}
#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;
#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 )
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
#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 )
{
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
#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 )
{
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
//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 )
{
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
#ifndef REGTEST
+int getc_unlocked( struct _PDCLIB_file_t * stream )
+{
+ return fgetc_unlocked( stream );
+}
+
int getc( struct _PDCLIB_file_t * stream )
{
return fgetc( stream );
#ifndef REGTEST
+int getchar_unlocked( void )
+{
+ return fgetc_unlocked( stdin );
+}
+
+
int getchar( void )
{
return fgetc( stdin );
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
#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 );
#ifndef REGTEST
+int putchar_unlocked( int c )
+{
+ return fputc_unlocked( c, stdout );
+}
+
int putchar( int c )
{
return fputc( c, stdout );
extern char * _PDCLIB_eol;
-int puts( const char * s )
+int puts_unlocked( const char * s )
{
if ( _PDCLIB_prepwrite( stdout ) == EOF )
{
}
}
+int puts( const char * s )
+{
+ flockfile( stdout );
+ int r = puts_unlocked( s );
+ funlockfile( stdout );
+ return r;
+}
+
#endif
#ifdef TEST
#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;
#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 )
{
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
#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;
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
#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;
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
#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 );
#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 );
#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;
#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 */
}
#ifndef REGTEST
#include <ctype.h>
-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;
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.
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