]> pd.if.org Git - pdclib/commitdiff
Added any files yet missing for stdio.h.
authorsolar <unknown>
Tue, 11 Jul 2006 05:58:21 +0000 (05:58 +0000)
committersolar <unknown>
Tue, 11 Jul 2006 05:58:21 +0000 (05:58 +0000)
15 files changed:
Notes.txt
Readme.txt
draft.c [deleted file]
functions/stdio/fgetc.c [new file with mode: 0644]
functions/stdio/fgetpos.c [new file with mode: 0644]
functions/stdio/fgets.c [new file with mode: 0644]
functions/stdio/fseek.c [new file with mode: 0644]
functions/stdio/fsetpos.c [new file with mode: 0644]
functions/stdio/ftell.c [new file with mode: 0644]
functions/stdio/perror.c [new file with mode: 0644]
functions/stdio/puts.c [new file with mode: 0644]
functions/stdio/rewind.c [new file with mode: 0644]
functions/stdio/ungetc.c [new file with mode: 0644]
platform/example/functions/stdio/tmpfile.c [new file with mode: 0644]
platform/example/functions/stdio/tmpnam.c [new file with mode: 0644]

index 13ade96220c406058fba38621fdaa2b0a84860b5..f2fd90a80e3190e8fdd08ebf6bded1544ff29d35 100644 (file)
--- a/Notes.txt
+++ b/Notes.txt
@@ -35,8 +35,8 @@ Everyone involved in the first, "public" attempt at PDCLib, for bearing with me
 when I restarted from scratch, thanks.
 
 Lennart Fridén and Sammy Nordström, who have been great pals even after I sunk
-another project that had eaten countless hours of work between the three of us,
-thanks.
+some other project that had eaten countless hours of work between the three of
+us, thanks.
 
 My wife and daughter, for sharing husband and daddy with this strange machine,
 thanks.
@@ -65,23 +65,21 @@ obsessive when it comes to coding style. ;-)
 - every function, every static data item that could possibly be shared, got its
   own implementation file. This means the library itself is probably larger than
   strictly necessary, and might take a couple of clock cycles longer to link,
-  but it reduces size of fully-linked object files / executables.
+  but it reduces size of object files and executables.
 
 - where possible, I tried to share functionality between similar functions (as
   can be seen in the atoi() and strtol() function families). This means one or
   two additional function calls, but again reduces memory footprint and eases
   maintenance of the library.
 
-- standard function arguments are named exactly as in the standard document.
+- function arguments are named exactly as in the standard document.
 
 - the standard is taken quite literally in places. For example, memcpy() really
   copies char-wise. This runs contrary to earlier claims of performance, but is
   consistent with the *letter* of the standard, and you will probably use your
   compiler builtins (through a platform overlay) anyhow.
 
-- every file (except the top-level *.txt files) has an Id and a Name tag, so
-  that the CVS Id string is on file for *every* code file, and the release tag
-  is on file for every code file in a release package.
+- every file has an Id tag, so that it is on file for *every* code file.
 
 - PDCLib code has no bias towards POSIX; indeed the absence of POSIX tidbits is
   one of its hallmarks. However, PDCLib also has no bias *against* POSIX, and
index 1ae4b90d0709a8fa8cf504e45e1d8ca7ace49b33..51d9875f5d4358e420b22f6bab7477064874d7f0 100644 (file)
@@ -54,10 +54,10 @@ Internals
 
 As a namespace convention, everything (files, typedefs, functions,
 macros) not defined in ISO/IEC 9899 is prefixed with _PDCLIB_*.
-As identifiers starting with '_' and a capital letter are reserved
-for the implementation, and the chances of you compiler using an
-identifier in the _PDCLIB_* range are slim, any strictly conforming
-application should work with PDCLib.
+The standard defines any identifiers starting with '_' and a capital
+letter as reserved for the implementation, and since the chances of
+your compiler using an identifier in the _PDCLIB_* range are slim,
+any strictly conforming application should work with PDCLib.
 
 PDCLib consists of several parts:
 
@@ -66,32 +66,43 @@ PDCLib consists of several parts:
 3) internal header files keeping complex stuff out of the standard
    headers;
 4) the central, platform-specific file _PDCLIB_config.h;
-5) optimization overlay implementation files (optional).
-
-The standard headers only contain what they are defined to contain.
-Where additional logic or macro magic is necessary, that is deferred
-to the internal files. This has been done so that the headers are
-actually educational as to what they provide (as opposed to how the
-library does it).
-
-There is a seperate implementation file for every function defined
-by the standard, named {function}.c. Not only does this avoid linking
-in huge amounts of unused code when you use but a single function,
-it also allows the optimization overlay to work (see below).
-
-Then there are internal header files, which contain all the "black
-magic" and "code fu" that were kept out of the standard headers. You
-should not have to touch them if you want to adapt PDCLib to a new
-platform. If you do, note that the PDCLib author would consider it
-a serious design flaw, and would be happy to fix it in the next PDCLib
-release. Any adaption work should be covered by the config header
-(and, possibly, the optimization overlay).
+5) platform-specific implementation files;
+6) platform-specific, optimized "overlay" implementations (optional).
+
+The standard headers (in ./includes/) only contain what they are
+defined to contain. Where additional logic or macro magic is
+necessary, that is deferred to the internal files. This has been done
+so that the headers are actually educational as to what they provide
+(as opposed to how the library does it).
+
+Note that there *might* be some feature to remove this additional
+level of indirection for a production release, to ease the workload
+put on the preprocessor.
+
+There is a seperate implementation file (in ./function/{header}/) for
+every function defined by the standard, named {function}.c. Not only
+does this avoid linking in huge amounts of unused code when you use
+but a single function, it also allows the optimization overlay to work
+(see below).
+
+(The directory ./functions/_PDCLIB/ contains internal and helper
+functions that are not part of the standard.)
+
+Then there are internal header files (in ./internal/), which contain
+all the "black magic" and "code fu" that was kept out of the standard
+headers. You should not have to touch them if you want to adapt PDCLib
+to a new platform. If you *do* have to touch them, note that the PDCLib
+author would consider it a serious design flaw, and would be happy to
+fix it in the next PDCLib release. Any adaption work should be covered
+by the steps detailed below.
 
 For adapting PDCLib to a new platform (the trinity of CPU, operating
-system, and compiler), open _PDCLIB_config.h in your favourite text
-editor, have a look at the comments, and modify it as appropriate for
-your platform. That should be all that is actually required for such
-an adaption (see previous paragraph).
+system, and compiler), make a copy of the ./platform/example/ directory
+(named after your target platform), and modify the files of your copy
+to suit the constraints of your platform. When you are done, copy the
+contents of your platform directory over the source directory structure
+of PDCLib (or link them into the appropriate places). That should be
+all that is actually required to make PDCLib work for your platform.
 
 Of course, your platform might provide more efficient replacements
 for the generic implementations offered by PDCLib. The math functions
@@ -115,17 +126,16 @@ so correctly, but they are not very efficient when compared to hand-
 crafted assembler or compiler build-ins. So the author wanted to
 provide a means to modify PDCLib to run more efficiently on a given
 platform, without cluttering the main branch with tons of #ifdef
-statements and "featureset defines" that grow stale quickly.
+statements and "featureset #defines" that grow stale quickly.
 
 The solution is the "optimization overlay". Every function has its
-own implementation file, and _PDCLIB_config.h should be the only
-header that must be modified. So, a platform-specific overlay is
-copied over the main PDCLib branch - replacing _PDCLIB_config.h and
-any number of implementation files - to create a PDCLib adapted /
-optimized for the platform in question. That overlay could be part
-of the PDCLib source tree (for established platforms where maintainers
-won't bother with PDCLib), or part of that platform's source tree
-(for under-development platforms PDCLib maintainers won't bother with).
+own implementation file, which makes it possible to replace them
+piecemeal by copying a platform-specific overlay over the main PDCLib
+branch to create a PDCLib adapted / optimized for the platform in
+question. That overlay could be part of the PDCLib source tree (for
+established platforms where maintainers won't bother with PDCLib), or
+part of that platform's source tree (for under-development platforms
+PDCLib maintainers won't bother with).
 
 So, to use PDCLib on your given platform, you unpack PDCLib (as you
 obviously have done already since you are reading this), and copy
@@ -155,8 +165,8 @@ Implementations for parts of <stdlib.h>. Still missing are the floating
 point conversions, and the wide-/multibyte-character functions.
 
 v0.5 - unreleased
-Implementations for parts of <stdio.h>. Bug fixes. Still no locale /
-wide-char support. Enabled all GCC compiler warnings I could find, and
-fixed everything that threw a warning. Fixed all open bugs in the v0.4
-release.
-
+Implementations for parts of <stdio.h>. Still no locale / wide-char
+support. Enabled all GCC compiler warnings I could find, and fixed
+everything that threw a warning. (You see this, maintainers of Open
+Source software? No warnings whatsoever. Stop telling me it cannot
+be done.) Fixed all known bugs in the v0.4 release.
diff --git a/draft.c b/draft.c
deleted file mode 100644 (file)
index 570f305..0000000
--- a/draft.c
+++ /dev/null
@@ -1,687 +0,0 @@
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/* These can be removed once integrated into PDCLIB make procedure */
-#undef TEST
-#include </home/solar/src/pdclib/functions/_PDCLIB/digits.c>
-#include </home/solar/src/pdclib/functions/_PDCLIB/Xdigits.c>
-
-/* Using an integer's bits as flags for both the conversion flags and length
-   modifiers.
-*/
-#define E_minus    1<<0
-#define E_plus     1<<1
-#define E_alt      1<<2
-#define E_space    1<<3
-#define E_zero     1<<4
-#define E_done     1<<5
-#define E_char     1<<6
-#define E_short    1<<7
-#define E_long     1<<8
-#define E_llong    1<<9
-#define E_intmax   1<<10
-#define E_size     1<<11
-#define E_ptrdiff  1<<12
-#define E_intptr   1<<13
-#define E_double   1<<14
-#define E_lower    1<<15
-#define E_unsigned 1<<16
-
-struct status_t
-{
-    int           base;  /* base to which the value shall be converted       */
-    int_fast32_t  flags; /* flags and length modifiers                       */
-    size_t        n;     /* maximum number of characters to be written       */
-    size_t        i;     /* number of characters already written             */
-    size_t        this;  /* number of output chars in the current conversion */
-    char *        s;     /* target buffer                                    */
-    size_t        width; /* width of current field                           */
-    size_t        prec;  /* precision of current field                       */
-    FILE *        stream;/* for to-stream output                             */
-    va_list       ap;    /* the argument stack passed to the printf function */
-};
-
-const char * parse_out( const char * spec, struct status_t * status );
-inline void test( size_t n, const char * expect, ... );
-int _PDCLIB_vsnprintf( char * buffer, size_t n, const char * format, va_list ap );
-int _PDCLIB_snprintf( char * s, size_t n, const char * format, ... );
-
-/* The following only for testing. */
-#include <limits.h>
-#include <string.h>
-
-int main( void )
-{
-    test( SIZE_MAX, "%hhd", CHAR_MIN );
-    test( SIZE_MAX, "%hhd", CHAR_MAX );
-    test( SIZE_MAX, "%hhd", 0 );
-    test( SIZE_MAX, "%hd", SHRT_MIN );
-    test( SIZE_MAX, "%hd", SHRT_MAX );
-    test( SIZE_MAX, "%hd", 0 );
-    test( SIZE_MAX, "%d", INT_MIN );
-    test( SIZE_MAX, "%d", INT_MAX );
-    test( SIZE_MAX, "%d", 0 );
-    test( SIZE_MAX, "%ld", LONG_MIN );
-    test( SIZE_MAX, "%ld", LONG_MAX );
-    test( SIZE_MAX, "%ld", 0l );
-    test( SIZE_MAX, "%lld", LLONG_MIN );
-    test( SIZE_MAX, "%lld", LLONG_MAX );
-    test( SIZE_MAX, "%lld", 0ll );
-    test( SIZE_MAX, "%hhu", UCHAR_MAX );
-    test( SIZE_MAX, "%hhu", (unsigned char)-1 );
-    test( SIZE_MAX, "%hu", USHRT_MAX );
-    test( SIZE_MAX, "%hu", (unsigned short)-1 );
-    test( SIZE_MAX, "%u", UINT_MAX );
-    test( SIZE_MAX, "%u", -1u );
-    test( SIZE_MAX, "%lu", ULONG_MAX );
-    test( SIZE_MAX, "%lu", -1ul );
-    test( SIZE_MAX, "%llu", ULLONG_MAX );
-    test( SIZE_MAX, "%llu", -1ull );
-    test( SIZE_MAX, "%X", UINT_MAX );
-    test( SIZE_MAX, "%#X", -1u );
-    test( SIZE_MAX, "%x", UINT_MAX );
-    test( SIZE_MAX, "%#x", -1u );
-    test( SIZE_MAX, "%o", UINT_MAX );
-    test( SIZE_MAX, "%#o", -1u );
-    test( SIZE_MAX, "%.0#o", 0 );
-    test( SIZE_MAX, "%+d", INT_MIN );
-    test( SIZE_MAX, "%+d", INT_MAX );
-    test( SIZE_MAX, "%+d", 0 );
-    test( SIZE_MAX, "%+u", UINT_MAX );
-    test( SIZE_MAX, "%+u", -1u );
-    test( SIZE_MAX, "% d", INT_MIN );
-    test( SIZE_MAX, "% d", INT_MAX );
-    test( SIZE_MAX, "% d", 0 );
-    test( SIZE_MAX, "% u", UINT_MAX );
-    test( SIZE_MAX, "% u", -1u );
-    test( SIZE_MAX, "%9d", INT_MIN );
-    test( SIZE_MAX, "%9d", INT_MAX );
-    test( SIZE_MAX, "%10d", INT_MIN );
-    test( SIZE_MAX, "%10d", INT_MAX );
-    test( SIZE_MAX, "%11d", INT_MIN );
-    test( SIZE_MAX, "%11d", INT_MAX );
-    test( SIZE_MAX, "%12d", INT_MIN );
-    test( SIZE_MAX, "%12d", INT_MAX );
-    test( SIZE_MAX, "%-9d", INT_MIN );
-    test( SIZE_MAX, "%-9d", INT_MAX );
-    test( SIZE_MAX, "%-10d", INT_MIN );
-    test( SIZE_MAX, "%-10d", INT_MAX );
-    test( SIZE_MAX, "%-11d", INT_MIN );
-    test( SIZE_MAX, "%-11d", INT_MAX );
-    test( SIZE_MAX, "%-12d", INT_MIN );
-    test( SIZE_MAX, "%-12d", INT_MAX );
-    test( SIZE_MAX, "%09d", INT_MIN );
-    test( SIZE_MAX, "%09d", INT_MAX );
-    test( SIZE_MAX, "%010d", INT_MIN );
-    test( SIZE_MAX, "%010d", INT_MAX );
-    test( SIZE_MAX, "%011d", INT_MIN );
-    test( SIZE_MAX, "%011d", INT_MAX );
-    test( SIZE_MAX, "%012d", INT_MIN );
-    test( SIZE_MAX, "%012d", INT_MAX );
-    test( SIZE_MAX, "%-09d", INT_MIN );
-    test( SIZE_MAX, "%-09d", INT_MAX );
-    test( SIZE_MAX, "%-010d", INT_MIN );
-    test( SIZE_MAX, "%-010d", INT_MAX );
-    test( SIZE_MAX, "%-011d", INT_MIN );
-    test( SIZE_MAX, "%-011d", INT_MAX );
-    test( SIZE_MAX, "%-012d", INT_MIN );
-    test( SIZE_MAX, "%-012d", INT_MAX );
-    test( 8, "%9d", INT_MAX );
-    test( 8, "%9d", INT_MIN );
-    test( 9, "%9d", INT_MAX );
-    test( 9, "%9d", INT_MIN );
-    test( 10, "%9d", INT_MAX );
-    test( 10, "%9d", INT_MIN );
-    test( 9, "%10d", INT_MAX );
-    test( 9, "%10d", INT_MIN );
-    test( 10, "%10d", INT_MAX );
-    test( 10, "%10d", INT_MIN );
-    test( 11, "%10d", INT_MAX );
-    test( 11, "%10d", INT_MIN );
-    test( 10, "%11d", INT_MAX );
-    test( 10, "%11d", INT_MIN );
-    test( 11, "%11d", INT_MAX );
-    test( 11, "%11d", INT_MIN );
-    test( 12, "%11d", INT_MAX );
-    test( 12, "%11d", INT_MIN );
-    test( 11, "%12d", INT_MAX );
-    test( 11, "%12d", INT_MIN );
-    test( 12, "%12d", INT_MAX );
-    test( 12, "%12d", INT_MIN );
-    test( 13, "%12d", INT_MAX );
-    test( 13, "%12d", INT_MIN );
-    test( SIZE_MAX, "%030.20d", INT_MAX );
-    test( SIZE_MAX, "%.6x", UINT_MAX );
-    test( SIZE_MAX, "%#6.3x", UINT_MAX );
-    test( SIZE_MAX, "%#3.6x", UINT_MAX );
-    test( SIZE_MAX, "%.6d", INT_MIN );
-    test( SIZE_MAX, "%6.3d", INT_MIN );
-    test( SIZE_MAX, "%3.6d", INT_MIN );
-    test( SIZE_MAX, "%#0.6x", UINT_MAX );
-    test( SIZE_MAX, "%#06.3x", UINT_MAX );
-    test( SIZE_MAX, "%#03.6x", UINT_MAX );
-    test( SIZE_MAX, "%#0.6d", INT_MAX );
-    test( SIZE_MAX, "%#06.3d", INT_MAX );
-    test( SIZE_MAX, "%#03.6d", INT_MAX );
-    test( SIZE_MAX, "%#+.6d", INT_MAX );
-    test( SIZE_MAX, "%#+6.3d", INT_MAX );
-    test( SIZE_MAX, "%#+3.6d", INT_MAX );
-    test( SIZE_MAX, "%+0.6d", INT_MAX );
-    test( SIZE_MAX, "%+06.3d", INT_MAX );
-    test( SIZE_MAX, "%+03.6d", INT_MAX );
-    test( SIZE_MAX, "- %d", INT_MAX );
-    test( SIZE_MAX, "- %d %% %d", INT_MAX, INT_MIN );
-    test( SIZE_MAX, "%c", 'x' );
-    test( SIZE_MAX, "%s", "abcdef" );
-    test( SIZE_MAX, "%p", 0xdeadbeef );
-    {
-        char buffer[50];
-        int val1, val2, val3, val4;
-        snprintf( buffer, SIZE_MAX, "123456%n789%n", &val1, &val2 );
-        _PDCLIB_snprintf( buffer, SIZE_MAX, "123456%n789%n", &val3, &val4 );
-        if ( ( val1 != val3 ) || ( val2 != val4 ) )
-        {
-            printf( "Output %d/%d\nExpect %d/%d\n\n", val1, val2, val3, val4 );
-        }
-    }
-    return 0;
-}
-
-/* This macro delivers a given character to either a memory buffer or a stream,
-   depending on the contents of 'status' (struct status_t).
-   x - the character to be delivered
-   i - pointer to number of characters already delivered in this call
-   n - pointer to maximum number of characters to be delivered in this call
-   s - the buffer into which the character shall be delivered
-*/
-#define DELIVER( x ) do { if ( status->i < status->n ) { if ( status->stream != NULL ) putc( x, status->stream ); else status->s[status->i] = x; } ++(status->i); } while ( 0 )
-
-/* This function recursively converts a given integer value to a given base
-   into a character string. Persistent information - like the number of digits
-   parsed so far - is recorded in a struct status_t, which allows to avoid
-   overwriting snprintf() limits, and enables the function to do the necessary
-   padding / prefixing of the character string eventually printed.
-*/
-static void int2base( intmax_t value, struct status_t * status )
-{
-    /* Registering the character being printed at the end of the function here
-       already so it will be taken into account when the deepestmost recursion
-       does the prefix / padding stuff.
-    */
-    ++(status->this);
-    if ( ( value / status->base ) != 0 )
-    {
-        /* More digits to be done - recurse deeper */
-        int2base( value / status->base, status );
-    }
-    else
-    {
-        /* We reached the last digit, the deepest point of our recursion, and
-           only now know how long the number to be printed actually is. Now we
-           have to do the sign, prefix, width, and precision padding stuff
-           before printing the numbers while we resurface from the recursion.
-        */
-        /* At worst, we need two prefix characters (hex prefix). */
-        char preface[3] = "\0";
-        size_t preidx = 0;
-        if ( ( status->flags & E_alt ) && ( status->base == 16 || status->base == 8 ) )
-        {
-            /* Octal / hexadecimal prefix for "%#" conversions */
-            preface[ preidx++ ] = '0';
-            if ( status->base == 16 )
-            {
-                preface[ preidx++ ] = ( status->flags & E_lower ) ? 'x' : 'X';
-            }
-        }
-        if ( value < 0 )
-        {
-            /* Negative sign for negative values - at all times. */
-            preface[ preidx++ ] = '-';
-        }
-        else if ( ! ( status->flags & E_unsigned ) )
-        {
-            /* plus sign / extra space are only for unsigned conversions */
-            if ( status->flags & E_plus )
-            {
-                preface[ preidx++ ] = '+';
-            }
-            else if ( status->flags & E_space )
-            {
-                preface[ preidx++ ] = ' ';
-            }
-        }
-        {
-        size_t prec_pads = ( status->prec > status->this ) ? ( status->prec - status->this ) : 0;
-        if ( ! ( status->flags & ( E_minus | E_zero ) ) )
-        {
-            /* Space padding is only done if no zero padding or left alignment
-               is requested. Leave space for any prefixes determined above.
-            */
-            /* The number of characters to be printed, plus prefixes if any. */
-            /* This line contained probably the most stupid, time-wasting bug
-               I've ever perpetrated. Greetings to Samface, DevL, and all
-               sceners at Breakpoint 2006.
-            */
-            size_t characters = preidx + ( ( status->this > status->prec ) ? status->this : status->prec );
-            if ( status->width > characters )
-            {
-                for ( int i = 0; i < status->width - characters; ++i )
-                {
-                    DELIVER( ' ' );
-                    ++(status->this);
-                }
-            }
-        }
-        /* Now we did the padding, do the prefixes (if any). */
-        preidx = 0;
-        while ( preface[ preidx ] != '\0' )
-        {
-            DELIVER( preface[ preidx++ ] );
-            ++(status->this);
-        }
-        if ( ( ! ( status->flags & E_minus ) ) && ( status->flags & E_zero ) )
-        {
-            /* If field is not left aligned, and zero padding is requested, do
-               so.
-            */
-            while ( status->this < status->width )
-            {
-                DELIVER( '0' );
-                ++(status->this);
-            }
-        }
-        /* Do the precision padding if necessary. */
-        for ( int i = 0; i < prec_pads; ++i )
-        {
-            DELIVER( '0' );
-        }
-        }
-    }
-    /* Recursion tail - print the current digit. */
-    {
-    int digit = value % status->base;
-    if ( digit < 0 )
-    {
-        digit *= -1;
-    }
-    if ( status->flags & E_lower )
-    {
-        /* Lowercase letters. Same array used for strto...(). */
-        DELIVER( _PDCLIB_digits[ digit ] );
-    }
-    else
-    {
-        /* Uppercase letters. Array only used here, only 0-F. */
-        DELIVER( _PDCLIB_Xdigits[ digit ] );
-    }
-    }
-}
-
-/* This function is to be called with spec pointing to the leading '%' of a
-   printf() conversion specifier, with ap being 
-*/
-const char * parse_out( const char * spec, struct status_t * status )
-{
-    const char * orig_spec = spec;
-    if ( *(++spec) == '%' )
-    {
-        DELIVER( *spec );
-        return ++spec;
-    }
-    /* Initializing status structure */
-    status->flags = 0;
-    status->base  = 0;
-    status->this  = 0;
-    status->width = 0;
-    status->prec  = 0;
-
-    /* First come 0..n flags */
-    do
-    {
-        switch ( *spec )
-        {
-            case '-':
-                status->flags |= E_minus;
-                ++spec;
-                break;
-            case '+':
-                status->flags |= E_plus;
-                ++spec;
-                break;
-            case '#':
-                status->flags |= E_alt;
-                ++spec;
-                break;
-            case ' ':
-                status->flags |= E_space;
-                ++spec;
-                break;
-            case '0':
-                status->flags |= E_zero;
-                ++spec;
-                break;
-            default:
-                status->flags |= E_done;
-                break;
-        }
-    } while ( ! ( status->flags & E_done ) );
-
-    /* Optional field width */
-    if ( *spec == '*' )
-    {
-        /* Retrieve width value from argument stack */
-        if ( ( status->width = va_arg( status->ap, int ) ) < 0 )
-        {
-            /* Negative value is '-' flag plus absolute value */
-            status->flags |= E_minus;
-            status->width *= -1;
-        }
-        ++spec;
-    }
-    else
-    {
-        /* If a width is given, strtol() will return its value. If not given,
-           strtol() will return zero. In both cases, endptr will point to the
-           rest of the conversion specifier - just what we need.
-        */
-        status->width = (int)strtol( spec, (char**)&spec, 10 );
-    }
-
-    /* Optional precision */
-    if ( *spec == '.' )
-    {
-        ++spec;
-        if ( *spec == '*' )
-        {
-            /* Retrieve precision value from argument stack. A negative value
-               is as if no precision is given - as precision is initalized to
-               EOF (negative), there is no need for testing for negative here.
-            */
-            status->prec = va_arg( status->ap, int );
-        }
-        else
-        {
-            char * endptr;
-            status->prec = (int)strtol( spec, &endptr, 10 );
-            if ( spec == endptr )
-            {
-                /* Decimal point but no number - bad conversion specifier. */
-                return orig_spec;
-            }
-            spec = endptr;
-        }
-        /* Having a precision cancels out any zero flag. */
-        status->flags ^= E_zero;
-    }
-
-    /* Optional length modifier
-       We step one character ahead in any case, and step back only if we find
-       there has been no length modifier (or step ahead another character if it
-       has been "hh" or "ll").
-    */
-    switch ( *(spec++) )
-    {
-        case 'h':
-            if ( *spec == 'h' )
-            {
-                status->flags |= E_char;
-                ++spec;
-            }
-            else
-            {
-                status->flags |= E_short;
-            }
-            break;
-        case 'l':
-            if ( *spec == 'l' )
-            {
-                status->flags |= E_llong;
-                ++spec;
-            }
-            else
-            {
-                status->flags |= E_long;
-            }
-            break;
-        case 'j':
-            status->flags |= E_intmax;
-            break;
-        case 'z':
-            status->flags |= E_size;
-            break;
-        case 't':
-            status->flags |= E_ptrdiff;
-            break;
-        case 'L':
-            status->flags |= E_double;
-            break;
-        default:
-            --spec;
-            break;
-    }
-
-    /* Conversion specifier */
-    switch ( *spec )
-    {
-        case 'd':
-            /* FALLTHROUGH */
-        case 'i':
-            status->base = 10;
-            break;
-        case 'o':
-            status->base = 8;
-            status->flags |= E_unsigned;
-            break;
-        case 'u':
-            status->base = 10;
-            status->flags |= E_unsigned;
-            break;
-        case 'x':
-            status->base = 16;
-            status->flags |= ( E_lower | E_unsigned );
-            break;
-        case 'X':
-            status->base = 16;
-            status->flags |= E_unsigned;
-            break;
-        case 'f':
-        case 'F':
-        case 'e':
-        case 'E':
-        case 'g':
-        case 'G':
-            break;
-        case 'a':
-        case 'A':
-            break;
-        case 'c':
-            /* TODO: Flags, wide chars. */
-            DELIVER( va_arg( status->ap, int ) );
-            return ++spec;
-        case 's':
-            /* TODO: Flags, wide chars. */
-            {
-                char * s = va_arg( status->ap, char * );
-                while ( *s != '\0' )
-                {
-                    DELIVER( *(s++) );
-                }
-                return ++spec;
-            }
-        case 'p':
-            /* TODO: E_long -> E_intptr */
-            status->base = 16;
-            status->flags |= ( E_lower | E_unsigned | E_alt | E_long );
-            break;
-        case 'n':
-           {
-               int * val = va_arg( status->ap, int * );
-               *val = status->i;
-               return ++spec;
-           }
-        default:
-            /* No conversion specifier. Bad conversion. */
-            return orig_spec;
-    }
-
-    /* Do the actual output based on our findings */
-    if ( status->base != 0 )
-    {
-        /* Integer conversions */
-        /* TODO: Check for invalid flag combinations. */
-        if ( status->flags & E_unsigned )
-        {
-            uintmax_t value;
-            switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_size ) )
-            {
-                case E_char:
-                    value = (uintmax_t)(unsigned char)va_arg( status->ap, int );
-                    break;
-                case E_short:
-                    value = (uintmax_t)(unsigned short)va_arg( status->ap, int );
-                    break;
-                case 0:
-                    value = (uintmax_t)va_arg( status->ap, unsigned int );
-                    break;
-                case E_long:
-                    value = (uintmax_t)va_arg( status->ap, unsigned long );
-                    break;
-                case E_llong:
-                    value = (uintmax_t)va_arg( status->ap, unsigned long long );
-                    break;
-                case E_size:
-                    value = (uintmax_t)va_arg( status->ap, size_t );
-                    break;
-            }
-            ++(status->this);
-            if ( ( value / status->base ) != 0 )
-            {
-                int2base( (intmax_t)(value / status->base), status );
-            }
-            int digit = value % status->base;
-            if ( digit < 0 )
-            {
-                digit *= -1;
-            }
-            if ( status->flags & E_lower )
-            {
-                DELIVER( _PDCLIB_digits[ digit ] );
-            }
-            else
-            {
-                DELIVER( _PDCLIB_Xdigits[ digit ] );
-            }
-        }
-        else
-        {
-            switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_intmax ) )
-            {
-                case E_char:
-                    int2base( (intmax_t)(char)va_arg( status->ap, int ), status );
-                    break;
-                case E_short:
-                    int2base( (intmax_t)(short)va_arg( status->ap, int ), status );
-                    break;
-                case 0:
-                    int2base( (intmax_t)va_arg( status->ap, int ), status );
-                    break;
-                case E_long:
-                    int2base( (intmax_t)va_arg( status->ap, long ), status );
-                    break;
-                case E_llong:
-                    int2base( (intmax_t)va_arg( status->ap, long long ), status );
-                    break;
-                case E_ptrdiff:
-                    int2base( (intmax_t)va_arg( status->ap, ptrdiff_t ), status );
-                    break;
-                case E_intmax:
-                    int2base( va_arg( status->ap, intmax_t ), status );
-                    break;
-            }
-        }
-        if ( status->flags & E_minus )
-        {
-            while ( status->this < status->width )
-            {
-                DELIVER( ' ' );
-                ++(status->this);
-            }
-        }
-        if ( status->i >= status->n )
-        {
-            status->s[status->n - 1] = '\0';
-        }
-    }
-    return ++spec;
-}
-
-inline void test( size_t n, const char * expect, ... )
-{
-    char * buffer1 = malloc( 50 );
-    char * buffer2 = malloc( 50 );
-    int myrc;
-    int rc;
-    va_list ap;
-    va_start( ap, expect );
-    myrc = _PDCLIB_vsnprintf( buffer1, n, expect, ap );
-    rc = vsnprintf( buffer2, n, expect, ap );
-    if ( ( strcmp( buffer1, buffer2 ) != 0 ) || ( myrc != rc ) )
-    {
-        printf( "Output '%s', RC %d\nExpect '%s', RC %d\n\n", buffer1, myrc, buffer2, rc );
-    }
-    free( buffer1 );
-    free( buffer2 );
-}
-
-int _PDCLIB_vsnprintf( char * buffer, size_t n, const char * format, va_list ap )
-{
-    struct status_t status = { 0, 0, n, 0, 0, buffer, 0, 0, NULL, ap };
-    while ( *format != '\0' )
-    {
-        const char * rc;
-        if ( ( *format != '%' ) || ( ( rc = parse_out( format, &status ) ) == format ) )
-        {
-            /* No conversion specifier, print verbatim */
-            buffer[ status.i++ ] = *(format++);
-        }
-        else
-        {
-            /* Continue parsing after conversion specifier */
-            format = rc;
-        }
-    }
-    buffer[ status.i ] = '\0';
-    return status.i;
-}
-
-int _PDCLIB_snprintf( char * s, size_t n, const char * format, ... )
-{
-    va_list ap;
-    va_start( ap, format );
-    return _PDCLIB_vsnprintf( s, n, format, ap );
-}
-
-#if 0
-int _PDCLIB_fprintf( FILE * stream, const char * format, va_list ap )
-{
-    struct status_t status = { 0, 0, SIZE_MAX, 0, 0, NULL, 0, 0, stream, ap };
-    while ( *format != '\0' )
-    {
-        const char * rc;
-        if ( ( *format != '%' ) || ( ( rc = parse_out( format, &status, ap ) ) == format ) )
-        {
-            /* No conversion specifier, print verbatim */
-            putc( *(format++), stream );
-        }
-        else
-        {
-            /* Continue parsing after conversion specifier */
-            format = rc;
-        }
-    }
-    return status.i;
-}
-#endif
diff --git a/functions/stdio/fgetc.c b/functions/stdio/fgetc.c
new file mode 100644 (file)
index 0000000..900cd0a
--- /dev/null
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/* fgetc( 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>
+
+#ifndef REGTEST
+
+int fgetc( struct _PDCLIB_file_t * stream )
+{
+    /* TODO: Implement. */
+    return 0;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/functions/stdio/fgetpos.c b/functions/stdio/fgetpos.c
new file mode 100644 (file)
index 0000000..b023bfe
--- /dev/null
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/* fgetpos( FILE * , fpos_t * )
+
+   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 REGTEST
+
+int fgetpos( struct _PDCLIB_file_t * _PDCLIB_restrict stream, _PDCLIB_fpos_t * _PDCLIB_restrict pos )
+{
+    /* TODO: Implement. */
+    return 0;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/functions/stdio/fgets.c b/functions/stdio/fgets.c
new file mode 100644 (file)
index 0000000..203d3ff
--- /dev/null
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/* fgets( char *, int, 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>
+
+#ifndef REGTEST
+
+char * fgets( char * _PDCLIB_restrict s, int n, struct _PDCLIB_file_t * _PDCLIB_restrict stream )
+{
+    /* TODO: Implement. */
+    return NULL;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/functions/stdio/fseek.c b/functions/stdio/fseek.c
new file mode 100644 (file)
index 0000000..f33f250
--- /dev/null
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/* fseek( FILE *, long int, 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 REGTEST
+
+int fseek( struct _PDCLIB_file_t * stream, long int offset, int whence )
+{
+    /* TODO: Implement. */
+    return 0;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/functions/stdio/fsetpos.c b/functions/stdio/fsetpos.c
new file mode 100644 (file)
index 0000000..e40be0b
--- /dev/null
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/* fsetpos( FILE *, const fpos_t * )
+
+   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 REGTEST
+
+int fsetpos( struct _PDCLIB_file_t * stream, const _PDCLIB_fpos_t * pos )
+{
+    /* TODO: Implement. */
+    return 0;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/functions/stdio/ftell.c b/functions/stdio/ftell.c
new file mode 100644 (file)
index 0000000..9838156
--- /dev/null
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/* ftell( 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>
+
+#ifndef REGTEST
+
+long int ftell( struct _PDCLIB_file_t * stream )
+{
+    /* TODO: Implement. */
+    return 0;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/functions/stdio/perror.c b/functions/stdio/perror.c
new file mode 100644 (file)
index 0000000..c59ca0b
--- /dev/null
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/* perror( const char * )
+
+   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 REGTEST
+
+void perror( const char * s )
+{
+    /* TODO: Implement. */
+    return;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/functions/stdio/puts.c b/functions/stdio/puts.c
new file mode 100644 (file)
index 0000000..40c9727
--- /dev/null
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/* puts( const char * )
+
+   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 REGTEST
+
+int puts( const char * s )
+{
+    /* TODO: Implement. */
+    return 0;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/functions/stdio/rewind.c b/functions/stdio/rewind.c
new file mode 100644 (file)
index 0000000..543e284
--- /dev/null
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/* frewind( 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>
+
+#ifndef REGTEST
+
+void rewind( struct _PDCLIB_file_t * stream )
+{
+    /* TODO: Implement. */
+    return;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/functions/stdio/ungetc.c b/functions/stdio/ungetc.c
new file mode 100644 (file)
index 0000000..fdafc9d
--- /dev/null
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/* ungetc( int, 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>
+
+#ifndef REGTEST
+
+int ungetc( int c, struct _PDCLIB_file_t * stream )
+{
+    /* TODO: Implement. */
+    return 0;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/platform/example/functions/stdio/tmpfile.c b/platform/example/functions/stdio/tmpfile.c
new file mode 100644 (file)
index 0000000..79c9569
--- /dev/null
@@ -0,0 +1,29 @@
+/* $Id$ */
+
+/* tmpfile( void )
+
+   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_int.h>
+
+struct _PDCLIB_file_t * tmpfile( void )
+{
+    /* TODO: Implement */
+    return NULL;
+}
+
+#endif REGTEST
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main()
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/platform/example/functions/stdio/tmpnam.c b/platform/example/functions/stdio/tmpnam.c
new file mode 100644 (file)
index 0000000..c4a0a4d
--- /dev/null
@@ -0,0 +1,31 @@
+/* $Id$ */
+
+/* tmpnam( char * )
+
+   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 <stdarg.h>
+
+#ifndef REGTEST
+
+char * tmpnam( char * s )
+{
+    /* TODO: Implement. */
+    return NULL;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    TESTCASE( NO_TESTDRIVER );
+    return TEST_RESULTS;
+}
+
+#endif