SubDirHdrs $(PDCLIB_TOP) platform posix internals ;\r
}\r
\r
-PDCLIB_TEST_LINKFLAGS += -nostdlib ;\r
-PDCLIB_TEST_LINKLIBS += -lgcc ;\r
+if $(OS) = "MACOSX" {\r
+ # Need to link libSystem\r
+} else {\r
+ PDCLIB_TEST_LINKFLAGS += -nostdlib ;\r
+ PDCLIB_TEST_LINKLIBS += -lgcc ;\r
+}\r
\r
PDCLIB_OPTIONS = nothread notime dlmalloc ;
\ No newline at end of file
--- /dev/null
+SubDir PDCLIB_TOP platform posix ;
+PDCLibConfig ;
\ No newline at end of file
#ifndef REGTEST
#include <_PDCLIB_glue.h>
-extern void _exit( int status ) _PDCLIB_NORETURN;
+extern void _exit( int status ) _PDCLIB_noreturn;
void _PDCLIB_Exit( int status )
{
int main( void )
{
+#ifndef REGTEST
int UNEXPECTED_RETURN = 0;
_PDCLIB_Exit( 0 );
TESTCASE( UNEXPECTED_RETURN );
+#endif
return TEST_RESULTS;
}
--- /dev/null
+/* _PDCLIB_allocpages( int const )
+
+ This file is part of the Public Domain C Library (PDCLib).
+ Permission is granted to use, modify, and / or redistribute at will.
+*/
+
+/* This is an example implementation of _PDCLIB_allocpages() (declared in
+ _PDCLIB_config.h), fit for use with POSIX kernels.
+*/
+
+#ifndef REGTEST
+#include <stdint.h>
+#include <stddef.h>
+#include <sys/mman.h>
+#include <_PDCLIB_glue.h>
+
+void * _PDCLIB_allocpages( size_t n )
+{
+ void *addr = mmap(
+ NULL, n * _PDCLIB_MALLOC_PAGESIZE, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+
+ if(addr != MAP_FAILED) {
+ return addr;
+ } else {
+ return NULL;
+ }
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+ return TEST_RESULTS;
+}
+
+#endif
--- /dev/null
+/* _PDCLIB_freepages( void *, size_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 an example implementation of _PDCLIB_allocpages() (declared in
+ _PDCLIB_config.h), fit for use with POSIX kernels.
+*/
+
+#ifndef REGTEST
+#include <stdint.h>
+#include <stddef.h>
+#include <sys/mman.h>
+#include <_PDCLIB_glue.h>
+
+void _PDCLIB_freepages( void * p, size_t n )
+{
+ munmap( p, n * _PDCLIB_MALLOC_PAGESIZE );
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+ return TEST_RESULTS;
+}
+
+#endif
\ No newline at end of file
{
if ( unlink( old ) == EOF )
{
- switch ( errno )
- {
- /* See the comments on implementation-defined errno values in
- <_PDCLIB_config.h>.
- */
- case EACCES:
- case EFAULT:
- case EIO:
- case EISDIR:
- case ELOOP:
- case ENAMETOOLONG:
- case ENOENT:
- case ENOMEM:
- case ENOTDIR:
- case EPERM:
- case EROFS:
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- default:
- /* This should be something like EUNKNOWN. */
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- }
return -1;
}
else
}
else
{
- switch ( errno )
- {
- /* See the comments on implementation-defined errno values in
- <_PDCLIB_config.h>.
- */
- case EACCES:
- case EEXIST:
- case EFAULT:
- case EIO:
- case ELOOP:
- case EMLINK:
- case ENAMETOOLONG:
- case ENOENT:
- case ENOMEM:
- case ENOSPC:
- case ENOTDIR:
- case EPERM:
- case EROFS:
- case EXDEV:
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- default:
- /* This should be something like EUNKNOWN. */
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- }
return EOF;
}
}
int main( void )
{
+#ifndef REGTEST
FILE * file;
remove( testfile1 );
remove( testfile2 );
/* remove both files */
remove( testfile1 );
remove( testfile2 );
+#endif
return TEST_RESULTS;
}
+++ /dev/null
-/* $Id$ */
-
-/* _PDCLIB_allocpages( int const )
-
- This file is part of the Public Domain C Library (PDCLib).
- Permission is granted to use, modify, and / or redistribute at will.
-*/
-
-/* This is an example implementation of _PDCLIB_allocpages() (declared in
- _PDCLIB_config.h), fit for use with POSIX kernels.
-*/
-
-#include <stdint.h>
-#include <stddef.h>
-
-int brk( void * );
-void * sbrk( intptr_t );
-
-#ifndef _PDCLIB_GLUE_H
-#define _PDCLIB_GLUE_H _PDCLIB_GLUE_H
-#include <_PDCLIB_glue.h>
-#endif
-
-static void * membreak = NULL;
-
-void * _PDCLIB_allocpages( int const n )
-{
- if ( membreak == NULL )
- {
- /* first call, make sure end-of-heap is page-aligned */
- intptr_t unaligned = 0;
- membreak = sbrk( 0 );
- unaligned = _PDCLIB_PAGESIZE - (intptr_t)membreak % _PDCLIB_PAGESIZE;
- if ( unaligned < _PDCLIB_PAGESIZE )
- {
- /* end-of-heap not page-aligned - adjust */
- if ( sbrk( unaligned ) != membreak )
- {
- /* error */
- return NULL;
- }
- membreak = (char *)membreak + unaligned;
- }
- }
- /* increasing or decreasing heap - standard operation */
- void * oldbreak = membreak;
- membreak = (void *)( (char *)membreak + ( n * _PDCLIB_PAGESIZE ) );
- if ( brk( membreak ) == 0 )
- {
- /* successful */
- return oldbreak;
- }
- else
- {
- /* out of memory */
- membreak = oldbreak;
- return NULL;
- }
-}
-
-#ifdef TEST
-#include <_PDCLIB_test.h>
-
-int main( void )
-{
-#ifndef REGTEST
- {
- char * startbreak = sbrk( 0 );
- TESTCASE( _PDCLIB_allocpages( 0 ) );
- TESTCASE( ( (char *)sbrk( 0 ) - startbreak ) <= _PDCLIB_PAGESIZE );
- startbreak = sbrk( 0 );
- TESTCASE( _PDCLIB_allocpages( 1 ) );
- TESTCASE( sbrk( 0 ) == startbreak + ( 1 * _PDCLIB_PAGESIZE ) );
- TESTCASE( _PDCLIB_allocpages( 5 ) );
- TESTCASE( sbrk( 0 ) == startbreak + ( 6 * _PDCLIB_PAGESIZE ) );
- TESTCASE( _PDCLIB_allocpages( -3 ) );
- TESTCASE( sbrk( 0 ) == startbreak + ( 3 * _PDCLIB_PAGESIZE ) );
- }
-#endif
- return TEST_RESULTS;
-}
-
-#endif
+++ /dev/null
-/* $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 an example implementation of _PDCLIB_close() fit for use with POSIX
- kernels.
-*/
-
-#include <stdio.h>
-
-#ifndef REGTEST
-#include <_PDCLIB_glue.h>
-
-extern int close( int fd );
-
-int _PDCLIB_close( int fd )
-{
- return close( fd );
-}
-
-#endif
-
-#ifdef TEST
-#include <_PDCLIB_test.h>
-
-int main( void )
-{
- /* No testdriver; tested in driver for _PDCLIB_open(). */
- return TEST_RESULTS;
-}
-
-#endif
+++ /dev/null
-/* $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 an example implementation of _PDCLIB_fillbuffer() fit for
- use with POSIX kernels.
-*/
-
-#include <stdio.h>
-
-#ifndef REGTEST
-#include <_PDCLIB_glue.h>
-
-#include </usr/include/errno.h>
-
-typedef long ssize_t;
-extern ssize_t read( int fd, void * buf, size_t count );
-
-int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream )
-{
- /* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */
- ssize_t rc = read( stream->handle, stream->buffer, stream->bufsize );
- if ( rc > 0 )
- {
- /* Reading successful. */
- if ( ! ( stream->status & _PDCLIB_FBIN ) )
- {
- /* TODO: Text stream conversion here */
- }
- stream->pos.offset += rc;
- stream->bufend = rc;
- stream->bufidx = 0;
- return 0;
- }
- if ( rc < 0 )
- {
- /* Reading error */
- switch ( errno )
- {
- /* See comments on implementation-defined errno values in
- <_PDCLIB_config.h>.
- */
- case EBADF:
- case EFAULT:
- case EINTR:
- case EINVAL:
- case EIO:
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- default:
- /* This should be something like EUNKNOWN. */
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- }
- stream->status |= _PDCLIB_ERRORFLAG;
- return EOF;
- }
- /* End-of-File */
- stream->status |= _PDCLIB_EOFFLAG;
- return EOF;
-}
-
-#endif
-
-#ifdef TEST
-#include <_PDCLIB_test.h>
-
-int main( void )
-{
- /* Testing covered by ftell.c */
- return TEST_RESULTS;
-}
-
-#endif
-
+++ /dev/null
-/* $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 an example implementation of _PDCLIB_flushbuffer() fit for
- use with POSIX kernels.
-*/
-
-#include <stdio.h>
-#include <string.h>
-
-#ifndef REGTEST
-#include <_PDCLIB_glue.h>
-
-#include </usr/include/errno.h>
-
-typedef long ssize_t;
-extern ssize_t write( int fd, const void * buf, size_t count );
-
-/* The number of attempts to complete an output buffer flushing before giving
- * up.
- * */
-#define _PDCLIB_IO_RETRIES 1
-
-/* What the system should do after an I/O operation did not succeed, before */
-/* trying again. (Empty by default.) */
-#define _PDCLIB_IO_RETRY_OP( stream )
-
-int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream )
-{
- if ( ! ( stream->status & _PDCLIB_FBIN ) )
- {
- /* TODO: Text stream conversion here */
- }
- /* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */
- _PDCLIB_size_t written = 0;
- int rc;
- /* Keep trying to write data until everything is written, an error
- occurs, or the configured number of retries is exceeded.
- */
- for ( unsigned int retries = _PDCLIB_IO_RETRIES; retries > 0; --retries )
- {
- rc = (int)write( stream->handle, stream->buffer + written, stream->bufidx - written );
- if ( rc < 0 )
- {
- /* Write error */
- switch ( errno )
- {
- /* See <_PDCLIB_config.h>. There should be differenciated errno
- handling here, possibly even a 1:1 mapping; but that is up
- to the individual platform.
- */
- case EBADF:
- case EFAULT:
- case EFBIG:
- case EINTR:
- case EINVAL:
- case EIO:
- case ENOSPC:
- case EPIPE:
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- default:
- /* This should be something like EUNKNOWN. */
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- }
- stream->status |= _PDCLIB_ERRORFLAG;
- /* Move unwritten remains to begin of buffer. */
- stream->bufidx -= written;
- memmove( stream->buffer, stream->buffer + written, stream->bufidx );
- return EOF;
- }
- written += (_PDCLIB_size_t)rc;
- stream->pos.offset += rc;
- if ( written == stream->bufidx )
- {
- /* Buffer written completely. */
- stream->bufidx = 0;
- return 0;
- }
- }
- /* Number of retries exceeded. You probably want a different errno value
- here.
- */
- _PDCLIB_errno = _PDCLIB_ERROR;
- stream->status |= _PDCLIB_ERRORFLAG;
- /* Move unwritten remains to begin of buffer. */
- stream->bufidx -= written;
- memmove( stream->buffer, stream->buffer + written, stream->bufidx );
- return EOF;
-}
-
-#endif
-
-
-#ifdef TEST
-#include <_PDCLIB_test.h>
-
-int main( void )
-{
- /* Testing covered by ftell.c */
- return TEST_RESULTS;
-}
-
-#endif
-
+++ /dev/null
-/* $Id$ */
-
-/* _PDCLIB_open( char const * const, int )
-
- This file is part of the Public Domain C Library (PDCLib).
- Permission is granted to use, modify, and / or redistribute at will.
-*/
-
-/* This is an example implementation of _PDCLIB_open() fit for use with POSIX
- kernels.
-*/
-
-#include <stdio.h>
-
-#ifndef REGTEST
-#include <_PDCLIB_glue.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "/usr/include/errno.h"
-
-int _PDCLIB_open( char const * const filename, unsigned int mode )
-{
- /* This is an example implementation of _PDCLIB_open() fit for use with
- POSIX kernels.
- */
- int osmode;
- switch ( mode & ( _PDCLIB_FREAD | _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_FRW ) )
- {
- case _PDCLIB_FREAD: /* "r" */
- osmode = O_RDONLY;
- break;
- case _PDCLIB_FWRITE: /* "w" */
- osmode = O_WRONLY | O_CREAT | O_TRUNC;
- break;
- case _PDCLIB_FAPPEND: /* "a" */
- osmode = O_WRONLY | O_APPEND | O_CREAT;
- break;
- case _PDCLIB_FREAD | _PDCLIB_FRW: /* "r+" */
- osmode = O_RDWR;
- break;
- case _PDCLIB_FWRITE | _PDCLIB_FRW: /* "w+" */
- osmode = O_RDWR | O_CREAT | O_TRUNC;
- break;
- case _PDCLIB_FAPPEND | _PDCLIB_FRW: /* "a+" */
- osmode = O_RDWR | O_APPEND | O_CREAT;
- break;
- default: /* Invalid mode */
- return -1;
- }
- int rc;
- if ( osmode & O_CREAT )
- {
- rc = open( filename, osmode, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
- }
- else
- {
- rc = open( filename, osmode );
- }
- if ( rc == -1 )
- {
- switch ( errno )
- {
- /* See the comments on implementation-defined errno values in
- <_PDCLIB_config.h>.
- */
- case EACCES:
- case EFAULT:
- case EINTR:
- case EISDIR:
- case ELOOP:
- case EMFILE:
- case ENAMETOOLONG:
- case ENFILE:
- case ENODEV:
- case ENOENT:
- case ENOMEM:
- case ENOSPC:
- case ENOTDIR:
- case EOVERFLOW:
- case EROFS:
- case ETXTBSY:
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- default:
- /* This should be something like EUNKNOWN. */
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- }
- }
- return rc;
-}
-
-#endif
-
-#ifdef TEST
-#include <_PDCLIB_test.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-int main( void )
-{
- /* This testdriver assumes POSIX, i.e. _PDCLIB_fd_t being int and being
- incremented by one on each successful open.
- */
- int fh;
- char buffer[ 10 ];
- remove( testfile );
- /* Trying to read non-existent file. */
- TESTCASE( _PDCLIB_open( testfile, _PDCLIB_FREAD ) == _PDCLIB_NOHANDLE );
- /* Writing to file, trying to read from it. */
- TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FWRITE ) ) != _PDCLIB_NOHANDLE );
- TESTCASE( write( fh, "test", 4 ) == 4 );
- TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 );
- TESTCASE( read( fh, buffer, 4 ) == -1 );
- TESTCASE( _PDCLIB_close( fh ) == 0 );
- /* Reading from file, trying to write to it. */
- TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FREAD ) ) != _PDCLIB_NOHANDLE );
- TESTCASE( write( fh, "test", 4 ) == -1 );
- TESTCASE( _PDCLIB_close( fh ) == 0 );
- /* Appending to file, trying to read from it. */
- TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FAPPEND ) ) != _PDCLIB_NOHANDLE );
- TESTCASE( write( fh, "app", 3 ) == 3 );
- TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 );
- TESTCASE( read( fh, buffer, 10 ) == -1 );
- TESTCASE( write( fh, "end", 3 ) == 3 );
- TESTCASE( _PDCLIB_close( fh ) == 0 );
- /* Reading and writing from file ("r+"). */
- TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FREAD | _PDCLIB_FRW ) ) != _PDCLIB_NOHANDLE );
- TESTCASE( read( fh, buffer, 10 ) == 10 );
- TESTCASE( memcmp( buffer, "testappend", 10 ) == 0 );
- TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 );
- TESTCASE( write( fh, "wedo", 4 ) == 4 );
- TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 );
- TESTCASE( read( fh, buffer, 10 ) == 10 );
- TESTCASE( memcmp( buffer, "wedoappend", 10 ) == 0 );
- TESTCASE( _PDCLIB_close( fh ) == 0 );
- /* Writing and reading from file ("w+"). */
- TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FWRITE | _PDCLIB_FRW ) ) != _PDCLIB_NOHANDLE );
- TESTCASE( write( fh, "test", 4 ) == 4 );
- TESTCASE( lseek( fh, 1, SEEK_SET ) == 1 );
- TESTCASE( read( fh, buffer, 2 ) == 2 );
- TESTCASE( memcmp( buffer, "es", 2 ) == 0 );
- TESTCASE( write( fh, "sie", 3 ) == 3 );
- TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 );
- TESTCASE( read( fh, buffer, 6 ) == 6 );
- TESTCASE( memcmp( buffer, "tessie", 6 ) == 0 );
- TESTCASE( _PDCLIB_close( fh ) == 0 );
- /* Appending and reading from file ("a+"). */
- TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FAPPEND | _PDCLIB_FRW ) ) != _PDCLIB_NOHANDLE );
- TESTCASE( write( fh, "baby", 4 ) == 4 );
- TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 );
- TESTCASE( read( fh, buffer, 10 ) == 10 );
- TESTCASE( memcmp( buffer, "tessiebaby", 10 ) == 0 );
- TESTCASE( _PDCLIB_close( fh ) == 0 );
- /* Cleaning up. */
- TESTCASE( remove( testfile ) == 0 );
- return TEST_RESULTS;
-}
-
-#endif
-
+++ /dev/null
-/* $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 <stdio.h>
-
-#ifndef _PDCLIB_GLUE_H
-#define _PDCLIB_GLUE_H
-#include <_PDCLIB_glue.h>
-#endif
-
-#include "/usr/include/errno.h"
-
-extern _PDCLIB_int64_t lseek64( int fd, _PDCLIB_int64_t offset, int whence );
-
-_PDCLIB_int64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int64_t offset, int whence )
-{
- switch ( whence )
- {
- case SEEK_SET:
- case SEEK_CUR:
- case SEEK_END:
- /* EMPTY - OK */
- break;
- default:
- /* See comments on implementation-defined errno values in
- <_PDCLIB_config.h>.
- */
- _PDCLIB_errno = _PDCLIB_ERROR;
- return EOF;
- break;
- }
- _PDCLIB_int64_t rc = lseek64( stream->handle, offset, whence );
- if ( rc != EOF )
- {
- stream->ungetidx = 0;
- stream->bufidx = 0;
- stream->bufend = 0;
- stream->pos.offset = rc;
- return rc;
- }
- switch ( errno )
- {
- case EBADF:
- case EFAULT:
- /* See comments on implementation-defined errno values in
- <_PDCLIB_config.h>.
- */
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- default:
- /* This should be something like EUNKNOWN. */
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- }
- return EOF;
-}
-
-#ifdef TEST
-#include <_PDCLIB_test.h>
-
-int main( void )
-{
- /* Testing covered by ftell.c */
- return TEST_RESULTS;
-}
-
-#endif
-
static unsigned char _PDCLIB_sout_ungetbuf[_PDCLIB_UNGETCBUFSIZE];
static unsigned char _PDCLIB_serr_ungetbuf[_PDCLIB_UNGETCBUFSIZE];
-static struct _PDCLIB_file_t _PDCLIB_serr = { 2, _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 = { 1, _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 = { 0, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sin_ungetbuf, _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, NULL, &_PDCLIB_sout };
+extern _PDCLIB_fileops_t _PDCLIB_fileops;
+static struct _PDCLIB_file_t _PDCLIB_serr = { &_PDCLIB_fileops, { .sval = 2 }, 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, { .sval = 1 }, 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, { .sval = 0 }, 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;
#include <signal.h>
#ifndef REGTEST
-
#include <stdlib.h>
+#include <errno.h>
void (*_PDCLIB_sigabrt)( int ) = SIG_DFL;
void (*_PDCLIB_sigfpe)( int ) = SIG_DFL;
_PDCLIB_sigterm = func;
break;
default:
- /* The standard calls for an unspecified "positive value". You
- will probably want to define a specific value for this.
- */
- _PDCLIB_errno = 1;
+ errno = EINVAL;
return SIG_ERR;
}
return oldhandler;
--- /dev/null
+/* _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 <stdio.h>
+#include <stdint.h>
+#include <_PDCLIB_glue.h>
+#include <errno.h>
+#include <unistd.h>
+
+static bool readf( _PDCLIB_fd_t fd, void * buf, size_t length,
+ size_t * numBytesRead )
+{
+ ssize_t res = read(fd.sval, buf, length);
+ if(res == -1) {
+ return false;
+ } else {
+ *numBytesRead = res;
+ return true;
+ }
+}
+
+static bool writef( _PDCLIB_fd_t fd, const void * buf, size_t length,
+ size_t * numBytesWritten )
+{
+ ssize_t res = write(fd.sval, buf, length);
+ if(res == -1) {
+ return false;
+ } else {
+ *numBytesWritten = res;
+ return true;
+ }
+}
+
+/* Note: Assumes being compiled with an OFF64 programming model */
+
+static bool seekf( _PDCLIB_fd_t fd, int_fast64_t offset, int whence,
+ int_fast64_t* newPos )
+{
+ off_t npos = lseek( fd.sval, offset, whence );
+ if( npos == -1 ) {
+ return false;
+ } else {
+ *newPos = npos;
+ return true;
+ }
+}
+
+static void closef( _PDCLIB_fd_t self )
+{
+ close( self.sval );
+}
+
+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
--- /dev/null
+/* _PDCLIB_open(_PDCLIB_fd_t*, const _PDCLIB_fileops_t**,
+ char const*, unsigned int)
+
+ 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 <_PDCLIB_glue.h>
+#include <_PDCLIB_io.h>
+#include <fcntl.h>
+
+extern const _PDCLIB_fileops_t _PDCLIB_fileops;
+
+bool _PDCLIB_open(
+ _PDCLIB_fd_t* fd, const _PDCLIB_fileops_t** ops,
+ char const * filename, unsigned int mode )
+{
+ int osmode;
+ switch ( mode & ( _PDCLIB_FREAD | _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_FRW ) )
+ {
+ case _PDCLIB_FREAD: /* "r" */
+ osmode = O_RDONLY;
+ break;
+ case _PDCLIB_FWRITE: /* "w" */
+ osmode = O_WRONLY | O_CREAT | O_TRUNC;
+ break;
+ case _PDCLIB_FAPPEND: /* "a" */
+ osmode = O_WRONLY | O_APPEND | O_CREAT;
+ break;
+ case _PDCLIB_FREAD | _PDCLIB_FRW: /* "r+" */
+ osmode = O_RDWR;
+ break;
+ case _PDCLIB_FWRITE | _PDCLIB_FRW: /* "w+" */
+ osmode = O_RDWR | O_CREAT | O_TRUNC;
+ break;
+ case _PDCLIB_FAPPEND | _PDCLIB_FRW: /* "a+" */
+ osmode = O_RDWR | O_APPEND | O_CREAT;
+ break;
+ default: /* Invalid mode */
+ return -1;
+ }
+
+ fd->sval = open(filename, osmode,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ if(fd->sval == -1) {
+ return false;
+ }
+
+ *ops = &_PDCLIB_fileops;
+ return true;
+}
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+ return TEST_RESULTS;
+}
+
+#endif
\ No newline at end of file
#include <string.h>
-#include "/usr/include/errno.h"
-
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
extern int unlink( const char * pathname );
int remove( const char * pathname )
{
- int rc;
struct _PDCLIB_file_t * current = _PDCLIB_filelist;
while ( current != NULL )
{
}
current = current->next;
}
- if ( ( rc = unlink( pathname ) ) == -1 )
- {
- switch ( errno )
- {
- /* See the comments on implementation-defined errno values in
- <_PDCLIB_config.h>.
- */
- case EACCES:
- case EFAULT:
- case EIO:
- case EISDIR:
- case ELOOP:
- case ENAMETOOLONG:
- case ENOENT:
- case ENOMEM:
- case ENOTDIR:
- case EPERM:
- case EROFS:
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- default:
- /* This should be something like EUNKNOWN. */
- _PDCLIB_errno = _PDCLIB_ERROR;
- break;
- }
- }
- return rc;
+ return unlink( pathname );
}
#endif
#include <fcntl.h>
#include <unistd.h>
-extern struct _PDCLIB_file_t * _PDCLIB_filelist;
+extern const _PDCLIB_fileops_t _PDCLIB_fileops;
-/* This is an example implementation of tmpfile() fit for use with POSIX
- kernels.
-*/
-struct _PDCLIB_file_t * tmpfile( void )
+FILE* _PDCLIB_nothrow tmpfile( void )
{
- FILE * rc;
- /* This is the chosen way to get high-quality randomness. Replace as
- appropriate.
- */
- FILE * randomsource = fopen( "/proc/sys/kernel/random/uuid", "rb" );
- char filename[ L_tmpnam ];
- _PDCLIB_fd_t fd;
- if ( randomsource == NULL )
+
+ /* Good quality random source */
+ int urandom = open( "/dev/urandom", O_RDONLY | O_CLOEXEC );
+ if(urandom == -1)
{
+ // TODO: errno!
return NULL;
}
+
+ int fd;
+ char filename[ L_tmpnam ];
for ( ;; )
{
- /* Get a filename candidate. What constitutes a valid filename and
- where temporary files are usually located is platform-dependent,
- which is one reason why this function is located in the platform
- overlay. The other reason is that a *good* implementation should
- use high-quality randomness instead of a pseudo-random sequence to
- generate the filename candidate, which is *also* platform-dependent.
- */
- unsigned int random;
- fscanf( randomsource, "%u", &random );
- sprintf( filename, "/tmp/%u.tmp", random );
+ long long randnum;
+ if( read(urandom, &randnum, sizeof randnum ) != sizeof randnum )
+ {
+ // TODO: errno!
+ close( urandom );
+ return NULL;
+ }
+
+ sprintf( filename, "/tmp/%llx.tmp", randnum );
/* Check if file of this name exists. Note that fopen() is a very weak
check, which does not take e.g. access permissions into account
(file might exist but not readable). Replace with something more
{
break;
}
- close( fd );
}
- fclose( randomsource );
- /* See fopen(). */
- if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + L_tmpnam + BUFSIZ ) ) == NULL )
+ close( urandom );
+
+ FILE* rc = _PDCLIB_fvopen(((_PDCLIB_fd_t){ .sval = fd}), &_PDCLIB_fileops,
+ _PDCLIB_FWRITE | _PDCLIB_FRW |
+ _PDCLIB_DELONCLOSE, filename);
+ if( rc == NULL )
{
- /* No memory to set up FILE structure */
close( fd );
return NULL;
}
- rc->status = _PDCLIB_filemode( "wb+" ) | _IOLBF | _PDCLIB_DELONCLOSE;
- rc->handle = fd;
- rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t );
- rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE;
- rc->buffer = rc->filename + L_tmpnam;
- strcpy( rc->filename, filename );
- rc->bufsize = BUFSIZ;
- rc->bufidx = 0;
- rc->ungetidx = 0;
- rc->next = _PDCLIB_filelist;
- _PDCLIB_filelist = rc;
+
return rc;
}
--- /dev/null
+#ifndef _PDCLIB_ERRNO_H
+#define _PDCLIB_ERRNO_H
+#include <sys/errno.h>
+#endif
#endif
#define _PDCLIB_LLONG_BYTES 8
+// Match Darwin headers
+#define _PDCLIB_INT64_IS_LLONG
+
/* <stdlib.h> defines the div() function family that allows taking quotient */
/* and remainder of an integer division in one operation. Many platforms */
/* support this in hardware / opcode, and the standard permits ordering of */
/* Large enough an integer to hold all character codes of the largest supported
locale.
*/
-#define _PDCLIB_wint signed int
-#define _PDCLIB_wchar unsigned int
-#define _PDCLIB_WCHAR UINT
+#define _PDCLIB_wint int
+#define _PDCLIB_wchar int
+#define _PDCLIB_WCHAR INT
#define _PDCLIB_intptr long
#define _PDCLIB_INTPTR LONG
*/
#define _PDCLIB_UNGETCBUFSIZE 1
-/* errno -------------------------------------------------------------------- */
-
-/* These are the values that _PDCLIB_errno can be set to by the library.
-
- By keeping PDCLib's errno in the _PDCLIB_* namespace, the library is capable
- to "translate" between errno values used by the hosting operating system and
- those used and passed out by the library.
-
- Example: In the example platform, the remove() function uses the unlink()
- system call as backend. Linux sets its errno to EISDIR if you try to unlink()
- a directory, but POSIX demands EPERM. Within the remove() function, you can
- catch the 'errno == EISDIR', and set '_PDCLIB_errno = _PDCLIB_EPERM'. Anyone
- using PDCLib's <errno.h> will "see" EPERM instead of EISDIR (the _PDCLIB_*
- prefix removed by <errno.h> mechanics).
-
- If you do not want that kind of translation, you might want to "match" the
- values used by PDCLib with those used by the host OS, as to avoid confusion.
-
- The C standard only defines three distinct errno values: ERANGE, EDOM, and
- EILSEQ. The standard leaves it up to "the implementation" whether there are
- any more beyond those three. There is some controversy as to whether errno is
- such a good idea at all, so you might want to come up with a different error
- reporting facility for your platform.
-
- Things used to say "Since errno values beyond the three defined by the
- standard are not portable anyway (unless you look at POSIX), having your own
- error reporting facility would not hurt anybody either." at this point.
- However, then somebody birthed C++11 into the world, which copied POSIX's
- errno values into C++. Yes, even EINTR. Therefore, this library defines
- them. That said, thats nothing stopping you from using your own error
- reporting facility for things outside the C library.
-
- Sometimes the standard says to set errno to indicate an error, but does not
- prescribe a value. We will use a value from the following list. If POSIX
- defines a value, we use that; otherwise, we use as seems suitable.
-
- If porting to a system which uses an errno-like reporting system (e.g. a
- UNIX), you'll probably want to define them to match what the OS uses
-*/
-/* C errno values */
-#define _PDCLIB_ERANGE 1
-#define _PDCLIB_EDOM 2
-#define _PDCLIB_EILSEQ 3
-
-/* C++11/POSIX errno values */
-#define _PDCLIB_E2BIG 4
-#define _PDCLIB_ECONNRESET 5
-#define _PDCLIB_EISCONN 6
-#define _PDCLIB_ENOENT 7
-#define _PDCLIB_ENOTRECOVERABLE 8
-#define _PDCLIB_EROFS 9
-#define _PDCLIB_EACCES 10
-#define _PDCLIB_EDEADLK 11
-#define _PDCLIB_EISDIR 12
-#define _PDCLIB_ENOEXEC 13
-#define _PDCLIB_ENOTSOCK 14
-#define _PDCLIB_ESPIPE 15
-#define _PDCLIB_EADDRINUSE 16
-#define _PDCLIB_EDESTADDRREQ 17
-#define _PDCLIB_ELOOP 18
-#define _PDCLIB_ENOLCK 19
-#define _PDCLIB_ENOTSUPP 20
-#define _PDCLIB_ESRCH 21
-#define _PDCLIB_EADDRNOTAVAIL 22
-#define _PDCLIB_EMFILE 23
-#define _PDCLIB_ENOLINK 24
-#define _PDCLIB_ENOTTY 25
-#define _PDCLIB_ETIME 26
-#define _PDCLIB_EAFNOSUPPORT 27
-#define _PDCLIB_EEXIST 28
-#define _PDCLIB_EMLINK 29
-#define _PDCLIB_ENOMEM 30
-#define _PDCLIB_ENXIO 31
-#define _PDCLIB_ETIMEDOUT 32
-#define _PDCLIB_EAGAIN 33
-#define _PDCLIB_EFAULT 34
-#define _PDCLIB_EMSGSIZE 35
-#define _PDCLIB_ENOMSG 36
-#define _PDCLIB_EOPNOTSUPP 37
-#define _PDCLIB_ETXTBSY 38
-#define _PDCLIB_EALREADY 39
-#define _PDCLIB_EFBIG 40
-#define _PDCLIB_ENAMETOOLONG 41
-#define _PDCLIB_ENOPROTOOPT 42
-#define _PDCLIB_EOVERFLOW 43
-#define _PDCLIB_EWOULDBLOCK _PDCLIB_EAGAIN
-#define _PDCLIB_EBADF 44
-#define _PDCLIB_EHOSTUNREACH 45
-#define _PDCLIB_ENETDOWN 46
-#define _PDCLIB_ENOSPC 47
-#define _PDCLIB_EOWNERDEAD 48
-#define _PDCLIB_EXDEV 49
-#define _PDCLIB_EBADMSG 50
-#define _PDCLIB_EIDRM 51
-#define _PDCLIB_ENETRESET 52
-#define _PDCLIB_ENOSR 53
-#define _PDCLIB_EPERM 54
-#define _PDCLIB_EBUSY 55
-#define _PDCLIB_ENETUNREACH 56
-#define _PDCLIB_ENOSTR 57
-#define _PDCLIB_EPIPE 58
-#define _PDCLIB_ECANCELED 59
-#define _PDCLIB_EINPROGRESS 60
-#define _PDCLIB_ENFILE 61
-#define _PDCLIB_ENOSYS 62
-#define _PDCLIB_EPROTO 63
-#define _PDCLIB_ECHILD 64
-#define _PDCLIB_EINTR 65
-#define _PDCLIB_ENOBUFS 66
-#define _PDCLIB_ENOTCONN 67
-#define _PDCLIB_EPROTONOSUPPORT 68
-#define _PDCLIB_ECONNABORTED 69
-#define _PDCLIB_EINVAL 70
-#define _PDCLIB_ENODATA 71
-#define _PDCLIB_ENOTDIR 72
-#define _PDCLIB_EPROTOTYPE 73
-
#endif