]> pd.if.org Git - pdclib/commitdiff
Intermediate work, checked in for safekeeping as I pick up working on this again.
authorsolar <unknown>
Wed, 28 May 2008 06:16:15 +0000 (06:16 +0000)
committersolar <unknown>
Wed, 28 May 2008 06:16:15 +0000 (06:16 +0000)
17 files changed:
Makefile
Readme.txt
functions/_PDCLIB/fflush.c
functions/_PDCLIB/filemode.c
functions/_PDCLIB/strtox_main.c
functions/stdlib/qsort.c
functions/stdlib/strtol.c
functions/stdlib/strtoll.c
functions/stdlib/strtoul.c
functions/stdlib/strtoull.c
internals/_PDCLIB_aux.h
internals/_PDCLIB_glue.h
internals/_PDCLIB_int.h
platform/example/functions/_PDCLIB/_Exit.c
platform/example/functions/_PDCLIB/open.c
platform/example/functions/_PDCLIB/write.c
platform/example/internals/_PDCLIB_config.h

index ed78f423f6a4e757d9f1d8c24822bb39c87d6a59..bfd64b93e3f03bacdbf87dcf34cfb9b95955598b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ SRCFILES := $(shell find $(PROJDIRS) -mindepth 1 -maxdepth 3 -name "*.c")
 # All header files of the project
 HDRFILES := $(shell find $(PROJDIRS) -mindepth 1 -maxdepth 3 -name "*.h")
 # All .c files in functions/_PDCLIB that do not have a regression test driver
-INTFILES := _Exit atomax digits open print remove rename seed stdinit strtox_main strtox_prelim cleanstream fflush
+INTFILES := _Exit atomax digits open print remove rename seed stdinit strtox_main strtox_prelim cleanstream fflush filemode
 # All object files in the library
 OBJFILES := $(patsubst %.c,%.o,$(SRCFILES))
 # All test drivers (.t)
@@ -27,9 +27,10 @@ PATCHFILES1 := $(shell ls platform/example/functions/_PDCLIB/*.c)
 # All files in platform/example/functions/stdlib (for development only)
 PATCHFILES2 := $(shell ls platform/example/functions/stdlib/*.c)
 
-CFLAGS := -Wall -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wconversion -Wstrict-prototypes -fno-builtin
+WARNINGS := -Wall -Wextra -pedantic -Wno-unused-parameter -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wconversion -fno-builtin 
+CFLAGS := -g -std=c99 -I./internals $(WARNINGS) $(USERFLAGS)
 
-.PHONY: all clean dist test tests testdrivers regtests regtestdrivers todos fixmes find links unlink help
+.PHONY: all clean srcdist bindist test tests testdrivers regtests regtestdrivers todos fixmes find links unlink help
 
 all: pdclib.a
 
@@ -38,16 +39,16 @@ pdclib.a: $(OBJFILES)
        @ar rc pdclib.a $?
        @echo
 
-test: $(FILE)
-       $(FILE)
+test: functions/$(FILE)
+       functions/$(FILE)
 
 tests: testdrivers
-       -@rc=0; count=0; echo; for file in $(TSTFILES); do echo " TST   $$file"; ./$$file; rc=`expr $$rc + $$?`; count=`expr $$count + 1`; done; echo; echo "Tests executed (linking PDCLib): $$count  Tests failed: $$rc"; echo
+       -@rc=0; count=0; failed=""; echo; for file in $(TSTFILES); do echo " TST        $$file"; ./$$file; test=$$?; if [ $$test != 0 ]; then rc=`expr $$rc + $$test`; failed="$$failed $$file"; fi; count=`expr $$count + 1`; done; echo; echo "Tests executed (linking PDCLib): $$count  Tests failed: $$rc"; echo; for file in $$failed; do echo "Failed: $$file"; done;
 
 testdrivers: $(TSTFILES)
 
 regtests: regtestdrivers
-       -@rc=0; count=0; echo; for file in $(REGFILES); do echo " RTST  $$file"; ./$$file; rc=`expr $$rc + $$?`; count=`expr $$count + 1`; done; echo; echo "Tests executed (linking system libc): $$count  Tests failed: $$rc"; echo
+       -@rc=0; count=0; failed=""; echo; for file in $(REGFILES); do echo " RTST       $$file"; ./$$file; test=$$?; if [ $$test != 0 ]; then rc=`expr $$rc + $$test`; failed="$$failed $$file"; fi; count=`expr $$count + 1`; done; echo; echo "Tests executed (linking system libc): $$count  Tests failed: $$rc"; echo; for file in $$failed; do echo "Failed: $$file"; done;
 
 regtestdrivers: $(REGFILES)
 
@@ -56,7 +57,7 @@ regtestdrivers: $(REGFILES)
 clean:
        @for file in $(OBJFILES) $(DEPFILES) $(TSTFILES) $(REGFILES) pdclib.a pdclib.tgz; do if [ -f $$file ]; then rm $$file; fi; done
 
-dist:
+srcdist:
        @tar czf pdclib.tgz $(ALLFILES)
 
 todos:
@@ -66,7 +67,7 @@ fixmes:
        -@for file in $(ALLFILES); do grep -H FIXME $$file; done; true
 
 find:
-       @find functions/ includes/ internals/ platform/ -name "*\.[ch]" -type f | xargs grep $$FIND
+       @find functions/ includes/ internals/ platform/ old_stdio/ -name "*\.[ch]" -type f | xargs grep $$FIND
 
 links:
        @echo "Linking platform/example..."
@@ -87,7 +88,7 @@ help:
        @echo
        @echo "all              - build pdclib.a"
        @echo "clean            - remove all object files, dependency files and test drivers"
-       @echo "dist             - build pdclib.tgz (source tarball)"
+       @echo "srcdist          - build pdclib.tgz (source tarball)"
        @echo "test             - test a single testdriver (Usage: FILE=\"test.[rt]\" make test)"
        @echo "tests            - build and run test drivers (link pdclib.a)"
        @echo "  testdrivers    - build but do not run test drivers"
@@ -102,15 +103,19 @@ help:
        @echo "%.t              - build an individual test driver"
        @echo "%.r              - build an individual regression test driver"
        @echo "help             - print this list"
+       @echo
+       @echo "Any additional compiler flags you want to use can be passed as USERFLAGS"
+       @echo "(Usage: USERFLAGS=\"flags\" make [...])."
 
 %.o: %.c Makefile
        @echo " CC      $(patsubst functions/%,%,$@)"
-       @$(CC) $(CFLAGS) -DNDEBUG -MMD -MP -MT "$*.d $*.t" -g -std=c99 -I./includes -I./internals -c $< -o $@
+       @$(CC) $(CFLAGS) -MMD -MP -MT "$*.d $*.t" -I./includes -c $< -o $@
 
 %.t: %.c Makefile pdclib.a
        @echo " CC      $(patsubst functions/%,%,$@)"
-       @$(CC) $(CFLAGS) -DTEST -g -std=c99 -I./includes -I./internals $< pdclib.a -o $@
+       @$(CC) $(CFLAGS) -DTEST -I./includes $< pdclib.a -o $@
 
 %.r: %.c Makefile
        @echo " CC      $(patsubst functions/%,%,$@)"
-       @$(CC) $(CFLAGS) -Wno-format -DTEST -DREGTEST -g -std=c99 -I./internals $< -o $@
+       @$(CC) $(CFLAGS) -Wno-format -DTEST -DREGTEST $< -o $@
+
index 3bae131be9255daf3b068e50cc82cd58c96f0793..36bdf936586c8a153e0a7caac9296fd539a0b601 100644 (file)
@@ -170,6 +170,19 @@ v0.4 - 2005-02-06
 Implementations for parts of <stdlib.h>. Still missing are the floating
 point conversions, and the wide-/multibyte-character functions.
 
+v0.4.1 - 2006-11-16
+With v0.5 (<stdio.h>) taking longer than expected, v0.4.1 was set up as
+a backport of bugfixes in the current development code.
+- #1  realloc( NULL, size ) fails           (fixed)
+- #2  stdlib.h - insufficient documentation (fixed)
+- #4  Misspelled name in credits            (fixed)
+- #5  malloc() splits off too-small nodes   (fixed)
+- #6  qsort() stack overflow                (fixed)
+- #7  malloc() bug in list handling         (fixed)
+- #8  strncmp() does not terminate at '\0'  (fixed)
+- #9  stdint.h dysfunctional                (fixed)
+- #10 NULL redefinition warnings            (fixed)
+
 v0.5 - unreleased
 Implementations for parts of <stdio.h>. Still no locale / wide-char
 support. Enabled all GCC compiler warnings I could find, and fixed
index 3d26b400d079611476859eb3d54cbf1eb90bd7d5..e8c99db75122ae33b17230f1c5b26e4932f96604 100644 (file)
@@ -1,27 +1,55 @@
 /* $Id$ */
 
-/* _PDCLIB_fflush( FILE * )
+/* _PDCLIB_flushbuffer( FILE * )
 
    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>
+#include <limits.h>
+#include <assert.h>
 
-int _PDCLIB_fflush( struct _PDCLIB_file_t * stream )
+#include <_PDCLIB_glue.h>
+
+_PDCLIB_size_t _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream, _PDCLIB_size_t written, int retries )
 {
-    if ( fwrite( stream->buffer, stream->bufidx, 1, stream ) == stream->bufidx )
-    {
-        stream->bufidx = 0;
-        return 0;
-    }
-    else
+    _PDCLIB_size_t n = stream->bufidx - written;
+    int count = _PDCLIB_write( stream, stream->buffer + written, ( n <= INT_MAX ? (int)n : INT_MAX ) );
+    written += count; /* if count is -1, we don't need written anyway */
+    switch ( count )
     {
-        stream->status |= _PDCLIB_ERRORFLAG;
-        return EOF;
+        case -1:
+            /* write error */
+            stream->status |= _PDCLIB_ERRORFLAG;
+            /* FIXME: Map host errno to PDCLib errno */
+            return 0;
+        case 0:
+            /* no characters written - retry */
+            if ( retries == _PDCLIB_FLUSH_RETRIES )
+            {
+                /* max. number of retries without characters being written */
+                stream->status |= _PDCLIB_ERRORFLAG;
+                /* FIXME: Set errno */
+                return 0;
+            }
+            _PDCLIB_FLUSH_RETRY_PREP;
+            return _PDCLIB_flushbuffer( stream, written, retries + 1 );
+        default:
+            /* If the following assert fails, we wrote more characters than
+               available in the buffer. (???)
+            */
+            assert( written <= stream->bufidx );
+            if ( written == stream->bufidx ) 
+            {
+                /* write complete */
+                stream->bufidx = 0;
+                return written;
+            }
+            return _PDCLIB_flushbuffer( stream, written, 0 );
     }
 }
-                
+    
 #ifdef TEST
 #include <_PDCLIB_test.h>
 
index 460cc6e4cfb5ec0dc2bdf53ae194ada37e303236..fd734fcf632325ce025bcbec8aaba0a988b6e905 100644 (file)
@@ -6,8 +6,6 @@
    Permission is granted to use, modify, and / or redistribute at will.
 */
 
-#ifndef REGTEST
-
 #include <stddef.h>
 
 /* Helper function that parses the C-style mode string passed to fopen() into
@@ -56,14 +54,11 @@ unsigned int _PDCLIB_filemode( char const * const mode )
     return 0;
 }
 
-#endif
-
 #ifdef TEST
 #include <_PDCLIB_test.h>
 
 int main( void )
 {
-#ifndef REGTEST
     TESTCASE( _PDCLIB_filemode( "r" ) == _PDCLIB_FREAD );
     TESTCASE( _PDCLIB_filemode( "w" ) == _PDCLIB_FWRITE );
     TESTCASE( _PDCLIB_filemode( "a" ) == _PDCLIB_FAPPEND );
@@ -79,10 +74,12 @@ int main( void )
     TESTCASE( _PDCLIB_filemode( "rb+" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW | _PDCLIB_FBIN ) );
     TESTCASE( _PDCLIB_filemode( "wb+" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) );
     TESTCASE( _PDCLIB_filemode( "ab+" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FRW | _PDCLIB_FBIN ) );
-#else
-    puts( " NOTEST fopen() test driver is PDCLib-specific." );
-#endif
+    TESTCASE( _PDCLIB_filemode( "x" ) == 0 );
+    TESTCASE( _PDCLIB_filemode( "r++" ) == 0 );
+    TESTCASE( _PDCLIB_filemode( "wbb" ) == 0 );
+    TESTCASE( _PDCLIB_filemode( "a+bx" ) == 0 );
     return TEST_RESULTS;
 }
 
 #endif
+
index bc14811335c736c73eab4597f9f704559b0aefba..fbdf8bbfad27a3fab8124eafa84937602c906ff9 100644 (file)
@@ -13,7 +13,7 @@
 #include <string.h>
 #include <stdint.h>
 
-_PDCLIB_uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, uintmax_t error, uintmax_t limval, uintmax_t limdigit, char * sign )
+_PDCLIB_uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, uintmax_t error, uintmax_t limval, int limdigit, char * sign )
 {
     _PDCLIB_uintmax_t rc = 0;
     int digit = -1;
@@ -58,17 +58,17 @@ int main( void )
     /* basic functionality */
     p = test;
     errno = 0;
-    TESTCASE( _PDCLIB_strtox_main( &p, 10u, (uintmax_t)999, (uintmax_t)12, (uintmax_t)3, &sign ) == 123 );
+    TESTCASE( _PDCLIB_strtox_main( &p, 10u, (uintmax_t)999, (uintmax_t)12, 3, &sign ) == 123 );
     TESTCASE( errno == 0 );
     TESTCASE( p == &test[3] );
     /* proper functioning to smaller base */
     p = test;
-    TESTCASE( _PDCLIB_strtox_main( &p, 8u, (uintmax_t)999, (uintmax_t)12, (uintmax_t)3, &sign ) == 0123 );
+    TESTCASE( _PDCLIB_strtox_main( &p, 8u, (uintmax_t)999, (uintmax_t)12, 3, &sign ) == 0123 );
     TESTCASE( errno == 0 );
     TESTCASE( p == &test[3] );
     /* overflowing subject sequence must still return proper endptr */
     p = test;
-    TESTCASE( _PDCLIB_strtox_main( &p, 4u, (uintmax_t)999, (uintmax_t)1, (uintmax_t)2, &sign ) == 999 );
+    TESTCASE( _PDCLIB_strtox_main( &p, 4u, (uintmax_t)999, (uintmax_t)1, 2, &sign ) == 999 );
     TESTCASE( errno == ERANGE );
     TESTCASE( p == &test[3] );
     TESTCASE( sign == '+' );
@@ -76,7 +76,7 @@ int main( void )
     errno = 0;
     p = fail;
     sign = '-';
-    TESTCASE( _PDCLIB_strtox_main( &p, 10u, (uintmax_t)999, (uintmax_t)99, (uintmax_t)8, &sign ) == 0 );
+    TESTCASE( _PDCLIB_strtox_main( &p, 10u, (uintmax_t)999, (uintmax_t)99, 8, &sign ) == 0 );
     TESTCASE( p == NULL );
     return TEST_RESULTS;
 }
index 084cd3ca4cf07675cca839812a5e4526283550da..6bb636f5631d5c50a51f9052c9b947f61507fb49 100644 (file)
@@ -41,9 +41,9 @@ void qsort( void * base, size_t nmemb, size_t size, int (*compar)( const void *,
 {
     char * i;
     char * j;
-    size_t thresh     = T * size;
-    char * base_      = (char *)base;
-    char * limit      = base_ + nmemb * size;
+    _PDCLIB_ptrdiff_t thresh  = T * size;
+    char * base_              = (char *)base;
+    char * limit              = base_ + nmemb * size;
     PREPARE_STACK;
 
     for ( ;; )
index 4a3b5a68f8c56e89fffddf53d961a1be03582759..04c8617541c0650b4bfb3a42b6b3b3ecb154a3c4 100644 (file)
@@ -21,12 +21,12 @@ long int strtol( const char * s, char ** endptr, int base )
     if ( base < 2 || base > 36 ) return 0;
     if ( sign == '+' )
     {
-        rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LONG_MAX, (uintmax_t)( LONG_MAX / base ), (uintmax_t)( LONG_MAX % base ), &sign );
+        rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LONG_MAX, (uintmax_t)( LONG_MAX / base ), (int)( LONG_MAX % base ), &sign );
     }
     else
     {
         /* FIXME: This breaks on some machines that round negatives wrongly */
-        rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LONG_MIN, (uintmax_t)( LONG_MIN / -base ), (uintmax_t)( -( LONG_MIN % base ) ), &sign );
+        rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LONG_MIN, (uintmax_t)( LONG_MIN / -base ), (int)( -( LONG_MIN % base ) ), &sign );
     }
     if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) s;
     return ( sign == '+' ) ? rc : -rc;
@@ -92,7 +92,7 @@ int main( void )
     TESTCASE( strtol( "0x80000000", NULL, 0 ) == LONG_MAX );
     TESTCASE( errno == ERANGE );
     errno = 0;
-    TESTCASE( strtol( "-0x7FFFFFFF", NULL, 0 ) == 0x80000001 );
+    TESTCASE( strtol( "-0x7FFFFFFF", NULL, 0 ) == (long)0x80000001 );
     TESTCASE( errno == 0 );
     TESTCASE( strtol( "-0x80000000", NULL, 0 ) == LONG_MIN );
     TESTCASE( errno == 0 );
index 768da391ef3f75f08bc71d946f236325ec7e2875..0eb8423f609c5246294f53e865a38df4e8f2af46 100644 (file)
@@ -21,13 +21,13 @@ long long int strtoll( const char * s, char ** endptr, int base )
     if ( base < 2 || base > 36 ) return 0;
     if ( sign == '+' )
     {
-        rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LLONG_MAX, (uintmax_t)( LLONG_MAX / base ), (uintmax_t)( LLONG_MAX % base ), &sign );
+        rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LLONG_MAX, (uintmax_t)( LLONG_MAX / base ), (int)( LLONG_MAX % base ), &sign );
     }
     else
     {
         /* FIXME: This breaks on some machines that round negatives wrongly */
         /* FIXME: Sign error not caught by testdriver */
-        rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LLONG_MIN, (uintmax_t)( LLONG_MIN / -base ), (uintmax_t)( -( LLONG_MIN % base ) ), &sign );
+        rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)LLONG_MIN, (uintmax_t)( LLONG_MIN / -base ), (int)( -( LLONG_MIN % base ) ), &sign );
     }
     if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) s;
     return ( sign == '+' ) ? rc : -rc;
@@ -93,7 +93,7 @@ int main( void )
     TESTCASE( strtoll( "0x8000000000000000", NULL, 0 ) == LLONG_MAX );
     TESTCASE( errno == ERANGE );
     errno = 0;
-    TESTCASE( strtoll( "-0x7FFFFFFFFFFFFFFF", NULL, 0 ) == 0x8000000000000001 );
+    TESTCASE( strtoll( "-0x7FFFFFFFFFFFFFFF", NULL, 0 ) == (long long)0x8000000000000001 );
     TESTCASE( errno == 0 );
     TESTCASE( strtoll( "-0x8000000000000000", NULL, 0 ) == LLONG_MIN );
     TESTCASE( errno == 0 );
index 415aadf3e7903c976794962dda5e4649956a4c1e..68f790af7a44fff289c9482d2ac6e31b1f997198 100644 (file)
@@ -19,7 +19,7 @@ unsigned long int strtoul( const char * s, char ** endptr, int base )
     char sign = '+';
     const char * p = _PDCLIB_strtox_prelim( s, &sign, &base );
     if ( base < 2 || base > 36 ) return 0;
-    rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)ULONG_MAX, (uintmax_t)( ULONG_MAX / base ), (uintmax_t)( ULONG_MAX % base ), &sign );
+    rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)ULONG_MAX, (uintmax_t)( ULONG_MAX / base ), (int)( ULONG_MAX % base ), &sign );
     if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) s;
     return ( sign == '+' ) ? rc : -rc;
 }
index de48b0f698869970aa75b9eac199c2ee1e35fad9..b4204e91bac79e1fb78e96159f70c0fb647ea1f1 100644 (file)
@@ -19,7 +19,7 @@ unsigned long long int strtoull( const char * s, char ** endptr, int base )
     char sign = '+';
     const char * p = _PDCLIB_strtox_prelim( s, &sign, &base );
     if ( base < 2 || base > 36 ) return 0;
-    rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)ULLONG_MAX, (uintmax_t)( ULLONG_MAX / base ), (uintmax_t)( ULLONG_MAX % base ), &sign );
+    rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)ULLONG_MAX, (uintmax_t)( ULLONG_MAX / base ), (int)( ULLONG_MAX % base ), &sign );
     if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) s;
     return ( sign == '+' ) ? rc : -rc;
 }
index 72e64cfd46409d4e2a40f8bcd557a3a9b4d61164..71196a566b64e83fccd2709c64cd7161acae8550 100644 (file)
@@ -1,65 +1,66 @@
-/* $Id$ */\r
-\r
-/* Auxiliary PDCLib code <_PDCLIB_aux.h>\r
-\r
-   This file is part of the Public Domain C Library (PDCLib).\r
-   Permission is granted to use, modify, and / or redistribute at will.\r
-*/\r
-\r
-/* -------------------------------------------------------------------------- */\r
-/* You should not have to edit anything in this file; if you DO have to, it   */\r
-/* would be considered a bug / missing feature: notify the author(s).         */\r
-/* -------------------------------------------------------------------------- */\r
-\r
-/* -------------------------------------------------------------------------- */\r
-/* Standard Version                                                           */\r
-/* -------------------------------------------------------------------------- */\r
-\r
-/* Many a compiler gets this wrong, so you might have to hardcode it instead. */\r
-\r
-#if __STDC__ != 1\r
-#error Compiler does not define _ _STDC_ _ to 1 (not standard-compliant)!\r
-#endif\r
-\r
-#ifndef __STDC_VERSION__\r
-#define _PDCLIB_C_VERSION 90\r
-#define _PDCLIB_restrict\r
-#define _PDCLIB_inline\r
-#elif __STDC_VERSION__ == 199409L\r
-#define _PDCLIB_C_VERSION 95\r
-#define _PDCLIB_restrict\r
-#define _PDCLIB_inline\r
-#elif __STDC_VERSION__ == 199901L\r
-#define _PDCLIB_C_VERSION 99\r
-#define _PDCLIB_restrict restrict\r
-#define _PDCLIB_inline inline\r
-#else\r
-#error Unsupported _ _STDC_VERSION_ _ (__STDC_VERSION__) (supported: ISO/IEC 9899:1990, 9899/AMD1:1995, and 9899:1999).\r
-#endif\r
-\r
-#ifndef __STDC_HOSTED__\r
-#error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)!\r
-#elif __STDC_HOSTED__ == 0\r
-#define _PDCLIB_HOSTED 0\r
-#elif __STDC_HOSTED__ == 1\r
-#define _PDCLIB_HOSTED 1\r
-#else\r
-#error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)!\r
-#endif\r
-\r
-#if _PDCLIB_C_VERSION != 99\r
-#error PDCLib might not be fully conforming to either C89 or C95 prior to v2.x.\r
-#endif\r
-\r
-/* -------------------------------------------------------------------------- */\r
-/* Helper macros:                                                             */\r
-/* _PDCLIB_cc( x, y ) concatenates two preprocessor tokens without extending  */\r
-/* _PDCLIB_concat( x, y ) concatenates two preprocessor tokens with extending */\r
-/* -------------------------------------------------------------------------- */\r
-\r
-#define _PDCLIB_cc( x, y )     x ## y\r
-#define _PDCLIB_concat( x, y ) _PDCLIB_cc( x, y )\r
-\r
-#define _PDCLIB_symbol2value( x ) #x\r
-#define _PDCLIB_symbol2string( x ) _PDCLIB_symbol2value( x )\r
-#define _PDCLIB_symbol2identity( x ) x\r
+/* $Id$ */
+
+/* Auxiliary PDCLib code <_PDCLIB_aux.h>
+
+   This file is part of the Public Domain C Library (PDCLib).
+   Permission is granted to use, modify, and / or redistribute at will.
+*/
+
+/* -------------------------------------------------------------------------- */
+/* You should not have to edit anything in this file; if you DO have to, it   */
+/* would be considered a bug / missing feature: notify the author(s).         */
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+/* Standard Version                                                           */
+/* -------------------------------------------------------------------------- */
+
+/* Many a compiler gets this wrong, so you might have to hardcode it instead. */
+
+#if __STDC__ != 1
+#error Compiler does not define _ _STDC_ _ to 1 (not standard-compliant)!
+#endif
+
+#ifndef __STDC_VERSION__
+#define _PDCLIB_C_VERSION 90
+#define _PDCLIB_restrict
+#define _PDCLIB_inline
+#elif __STDC_VERSION__ == 199409L
+#define _PDCLIB_C_VERSION 95
+#define _PDCLIB_restrict
+#define _PDCLIB_inline
+#elif __STDC_VERSION__ == 199901L
+#define _PDCLIB_C_VERSION 99
+#define _PDCLIB_restrict restrict
+#define _PDCLIB_inline inline
+#else
+#error Unsupported _ _STDC_VERSION_ _ (__STDC_VERSION__) (supported: ISO/IEC 9899:1990, 9899/AMD1:1995, and 9899:1999).
+#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
+
+#if _PDCLIB_C_VERSION != 99
+#error PDCLib might not be fully conforming to either C89 or C95 prior to v2.x.
+#endif
+
+/* -------------------------------------------------------------------------- */
+/* Helper macros:                                                             */
+/* _PDCLIB_cc( x, y ) concatenates two preprocessor tokens without extending  */
+/* _PDCLIB_concat( x, y ) concatenates two preprocessor tokens with extending */
+/* -------------------------------------------------------------------------- */
+
+#define _PDCLIB_cc( x, y )     x ## y
+#define _PDCLIB_concat( x, y ) _PDCLIB_cc( x, y )
+
+#define _PDCLIB_symbol2value( x ) #x
+#define _PDCLIB_symbol2string( x ) _PDCLIB_symbol2value( x )
+#define _PDCLIB_symbol2identity( x ) x
+
index 02ba7f9e40af87b38b7a8dc0b60ffab8a51c648e..db29f1ede847e6a5aa4e61887284f578b9ab8dbb 100644 (file)
@@ -15,7 +15,7 @@
 /* OS "glue", part 2                                                          */
 /* These are the functions you will have to touch, as they are where PDCLib   */
 /* interfaces with the operating system.                                      */
-/* They operate on data types partially defined by _PDCLIB_config.h.          */
+/* Some operate on data types defined by _PDCLIB_config.h.                    */
 /* -------------------------------------------------------------------------- */
 
 /* A system call that terminates the calling process, returning a given status
@@ -30,16 +30,18 @@ void _PDCLIB_Exit( int status ) _PDCLIB_NORETURN;
 */
 void * _PDCLIB_allocpages( int n );
 
-/* A system call that opens a file identified by name in a given mode, and
-   returns a file descriptor uniquely identifying that file.
+/* 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 n characters to a file identified by given file
-   descriptor. Return the number of characters actually written, or zero if
-   an error occured.
+/* A system call that writes up to n characters to a file identified by given
+   file descriptor. Return the number of characters actually written, or -1
+   if an error occured. Note that the number of characters may well be lower
+   than n without an error having occured.
 */
-_PDCLIB_size_t _PDCLIB_write( _PDCLIB_fd_t fd, char const * buffer, _PDCLIB_size_t n );
+int _PDCLIB_write( struct _PDCLIB_file_t * stream, char const * buffer, int n );
 
 /* A system call that reads n characters into a buffer, from a file identified
    by given file descriptor. Return the number of characters read.
@@ -65,5 +67,5 @@ int _PDCLIB_rename( const char * old, const char * new );
 /* A system call that returns one if the given file descriptor refers to an
    interactive device, and zero otherwise.
  */
-int _PDCLIB_isinteractive( _PDCLIB_fd_t fd );
+int _PDCLIB_interactive_stream( _PDCLIB_fd_t fd );
 
index 496f0e6e99c1f677600cbf8fcc905539bdcd3684..d4d0d9a00eb99e0e3762c554b9f7810b51bbe02c 100644 (file)
@@ -251,7 +251,7 @@ typedef unsigned _PDCLIB_intmax _PDCLIB_uintmax_t;
 /* Flags for representing mode (see fopen()). Note these must fit the same
    status field as the _IO?BF flags in <stdio.h> and the internal flags below.
 */
-#define _PDCLIB_FREAD    8u
+#define _PDCLIB_FREAD     8u
 #define _PDCLIB_FWRITE   16u
 #define _PDCLIB_FAPPEND  32u 
 #define _PDCLIB_FRW      64u
@@ -274,6 +274,7 @@ struct _PDCLIB_file_t
     _PDCLIB_size_t          bufidx;   /* index to point of action in buffer */
     _PDCLIB_size_t          bufend;   /* index to end of pre-read buffer */
     unsigned int            status;   /* misc. status bits */
+    char *                  filename; /* name used in fopen() / freopen() */
     struct _PDCLIB_file_t * next;     /* provisions for linked list handling */
 };
 
@@ -325,7 +326,7 @@ _PDCLIB_intmax_t _PDCLIB_atomax( const char * s );
 
 /* Two helper functions used by strtol(), strtoul() and long long variants.   */
 const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base );
-_PDCLIB_uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, _PDCLIB_uintmax_t error, _PDCLIB_uintmax_t limval, _PDCLIB_uintmax_t limdigit, char * sign );
+_PDCLIB_uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, _PDCLIB_uintmax_t error, _PDCLIB_uintmax_t limval, int limdigit, char * sign );
 
 /* Digits arrays used by various integer conversion functions */
 extern char _PDCLIB_digits[];
@@ -340,10 +341,16 @@ extern char _PDCLIB_Xdigits[];
 */
 const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status );
 
+/* Common denominator of puts() and fputs() */
+int _PDCLIB_puts( const char * s, const char * endl, struct _PDCLIB_file_t * stream );
+
 /* Parsing any fopen() style filemode string into a number of flags. */
 unsigned int _PDCLIB_filemode( const char * mode );
 
-/* Writing out unwritten buffers to file. Returns 0 if successful, EOF if error
-   occured. Sets error flag of stream in case of error. 
- */
-int _PDCLIB_fflush( struct _PDCLIB_file_t * stream );
+/* Writing out unwritten buffers of a specific stream. A NULL parameter (as is
+   possible with standard fflush()) is not supported.
+   Return 0 if successful, EOF if error occured. Set error flag of stream and
+   errno as appropriate in case of error.
+*/
+_PDCLIB_size_t _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream, _PDCLIB_size_t written, int retries );
+
index e90dfc6ee7bce4e9272cddaffc5bc6479eddb1e1..c3ecfbc373b26718be4d43024f17aedb801d9c3e 100644 (file)
@@ -30,7 +30,9 @@ void _PDCLIB_Exit( int status )
 
 int main( void )
 {
-    TESTCASE( NO_TESTDRIVER );
+    int UNEXPECTED_RETURN = 0;
+    _PDCLIB_Exit( 0 );
+    TESTCASE( UNEXPECTED_RETURN );
     return TEST_RESULTS;
 }
 
index 40d294f7de1150deabb11b2c601468ac330f58ee..fc82485aec2d730b3505ee6e3e655e1c83faa11b 100644 (file)
 
 int _PDCLIB_open( char const * const filename, unsigned int mode )
 {
-    /* FIXME: THIS IS NOT TO BE USED OUT-OF-THE-BOX.
-       It is a proof-of-concept implementation. E.g. a stream may only be fully
-       buffered IF IT CAN BE DETERMINED NOT TO REFER TO AN INTERACTIVE DEVICE.
-       This logic is not represented here, as this is the EXAMPLE platform, and
-       actual platform overlays may differ widely. Another point is the value
-       for permissions being hardcoded to 0664 for file creations.
+    /* This is an example implementation of _PDCLIB_open() fit for use with
+       POSIX kernels.
+       FIXME: The permissions of newly created files should not be hardcoded
+       here.
     */
     int osmode;
     switch ( mode & ~_PDCLIB_FBIN )
@@ -133,3 +131,4 @@ int main( void )
 }
 
 #endif
+
index d2841f694195376ab08ab0419af59fa2a0370cc0..67c833f6b9647af82acbe9827c5b0ec56ff3ce71 100644 (file)
@@ -7,26 +7,69 @@
 */
 
 #include <_PDCLIB_glue.h>
+#include <unistd.h>
 
 #ifndef REGTEST
 
-int write(int, const void *, unsigned int);
-
-_PDCLIB_size_t _PDCLIB_write( int fd, char const * buffer, _PDCLIB_size_t n )
+int _PDCLIB_write( struct _PDCLIB_file_t * stream, char const * buffer, int n )
 {
-    /* FIXME: Might return value < n, might return -1 on error */
-    return write( fd, buffer, n );
+    /* CAUTION: We assume ssize_t <=> int here. We do so implicitly so a smart
+       compiler can throw a warning in case it does not (and you missed this
+       note). Somewhere we have to cast the return value of write() to that of
+       _PDCLIB_write() (since the latter cannot use a return type not defined
+       by the standard). It would perhaps have been syntactically cleaner to
+       use ssize_t here and make the cast in the return statement, but this
+       way we don't have to include yet another non-standard header.
+    */
+    int rc;
+    if ( ( rc = write( stream->handle, buffer, (size_t)n ) ) == -1 )
+    {
+        /* Error encountered */
+        stream->status |= _PDCLIB_ERRORFLAG;
+        /* FIXME: Map the errno of the OS to PDCLib's errno */
+    }
+    return rc;
 }
 
 #endif
 
 #ifdef TEST
+/* TODO: Work around the following undef */
+#undef SEEK_SET
 #include <_PDCLIB_test.h>
 
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <errno.h>
+
+/* TODO: This uses POSIX system calls for now, should use standard calls
+   once they are in place. Clumsy sunny-path testing.
+*/
 int main( void )
 {
-    TESTCASE( NO_TESTDRIVER );
+    /* See the code comment at the functions' return statement above. */
+    int fd, r;
+    char * buffer = malloc( 13 );
+    TESTCASE( buffer != NULL );
+    strcpy( buffer, "Test output\n" );
+    /* Writing string to file */
+    TESTCASE( ( fd = open( "testfile", O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU ) ) != -1 );
+    struct _PDCLIB_file_t file = { fd, { 0, 0 }, buffer, BUFSIZ, 12, 0, 0, NULL };
+    TESTCASE( _PDCLIB_write( &file, file.buffer, 12 ) == 12 );
+    TESTCASE( close( file.handle ) != -1 );
+    /* Reading file back in */
+    TESTCASE( ( fd = open( "testfile", O_RDONLY ) ) != -1 );
+    memset( buffer, '\0', 13 );
+    TESTCASE( ( r = read( file.handle, (void *)buffer, 12 ) ) == 12 );
+    TESTCASE( strcmp( buffer, "Test output\n" ) == 0 );
+    TESTCASE( close( fd ) != -1 );
+    TESTCASE( unlink( "testfile" ) != -1 );
     return TEST_RESULTS;
 }
 
 #endif
+
index c807a1bc0fdd41fcee5c7ffc5a25e2da3b0e87cf..0df16791cd26f98afbd8f5c53343585d73a2295a 100644 (file)
 /* Misc                                                                       */
 /* -------------------------------------------------------------------------- */
 
+/* By default, PDCLib does some rather strict checking of function usage,     */
+/* especially in <stdio.h>. Things that are undefined by the standard - for   */
+/* example, mixing byte / wide operations or read / write operations without  */
+/* resetting the stream beforehand - are caught and handled graciously. This  */
+/* adds some complexity, and eats a couple of clock cycles. If you want to    */
+/* disable these checks, define _PDCLIB_STRICT to zero.                       */
+#define _PDCLIB_STRICT 1
+
 /* The character (sequence) your platform uses as newline.                    */
 #define _PDCLIB_endl "\n"
 
@@ -123,6 +131,7 @@ struct _PDCLIB_lldiv_t
    interrupts). The type itself is not defined in a freestanding environment,
    but its limits are. (Don't ask.)
 */
+#define _PDCLIB_sig_atomic int
 #define _PDCLIB_SIG_ATOMIC INT
 
 /* Result type of the 'sizeof' operator (must be unsigned) */
@@ -215,24 +224,25 @@ typedef char * _PDCLIB_va_list;
 
 /* Set this to the page size of your OS. If your OS does not support paging, set
    to an appropriate value. (Too small, and malloc() will call the kernel too
-   often. Too large, and you will waste memory.
+   often. Too large, and you will waste memory.)
 */
 #define _PDCLIB_PAGESIZE 4096
 
-/* Set this to the minimum memory node size. Any malloc() for a smaller siz
-   will be satisfied by a malloc() of this size instead.
+/* 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
 
 /* I/O ---------------------------------------------------------------------- */
 
-/* The unique file descriptor returned by _PDCLIB_open(). */
+/* 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 -1
+#define _PDCLIB_NOHANDLE ( (_PDCLIB_fd_t) -1 )
 
 /* A type in which to store file offsets. See fgetpos() / fsetpos(). */
 /* FIXME: The 'int' types here are placeholders. When changed, check out
@@ -247,7 +257,8 @@ typedef struct
 #define _PDCLIB_BUFSIZ 1024
 
 /* The minimum number of files the implementation can open simultaneously. Must
-   be at least 8.
+   be at least 8. Depends largely on how the bookkeeping is done by fopen() /
+   freopen() / fclose().
 */
 #define _PDCLIB_FOPEN_MAX 8
 
@@ -259,3 +270,14 @@ typedef struct
 
 /* Number of distinct file names that can be generated by tmpnam(). */
 #define _PDCLIB_TMP_MAX 50
+
+/* The number of times fflush() tries to write a file buffer before giving up
+   if no characters can be written.
+*/
+#define _PDCLIB_FLUSH_RETRIES 3
+/* This macro is executed after each try to write characters that results in
+   no characters being written. You can define this to be empty, wait a short
+   period of time, or whatever suits your environment.
+*/
+#define _PDCLIB_FLUSH_RETRY_PREP
+