]> pd.if.org Git - pdclib/commitdiff
Add _cbprintf/_vcbprintf (callback based printf formatters)
authorOwen Shepherd <owen.shepherd@e43.eu>
Tue, 7 Oct 2014 22:19:34 +0000 (23:19 +0100)
committerOwen Shepherd <owen.shepherd@e43.eu>
Tue, 7 Oct 2014 22:19:34 +0000 (23:19 +0100)
functions/stdio/_PDCLIB_print.c
functions/stdio/_PDCLIB_scan.c
functions/stdio/_cbprintf.c [new file with mode: 0644]
functions/stdio/_vcbprintf.c [new file with mode: 0644]
functions/stdio/vfprintf.c
functions/stdio/vscanf.c
functions/stdio/vsnprintf.c
includes/stdio.h
internals/_PDCLIB_int.h
internals/_PDCLIB_io.h

index 21177af13a2f49ad9e8e1d2025bd72544de50546..03623948d45ae8856548a07f0b4137196d9af3c3 100644 (file)
 #define E_TYPES (E_char | E_short | E_long | E_llong | E_intmax \
                 | E_size | E_ptrdiff | E_intptr)
 
 #define E_TYPES (E_char | E_short | E_long | E_llong | E_intmax \
                 | E_size | E_ptrdiff | E_intptr)
 
-/* This macro delivers a given character to either a memory buffer or a stream,
-   depending on the contents of 'status' (struct _PDCLIB_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 PUT( x ) \
-do { \
-    int character = x; \
-    if ( status->i < status->n ) { \
-        if ( status->stream != NULL ) \
-            _PDCLIB_putc_unlocked( character, status->stream ); \
-        else \
-            status->s[status->i] = character; \
-    } \
-    ++(status->i); \
-} while ( 0 )
-
-/* Maximum number of output characters = 
- *   number of bits in (u)intmax_t / number of bits per character in smallest 
+/* returns true if callback-based output succeeded; else false */
+static inline bool cbout(
+    struct _PDCLIB_status_t * status,
+    const void * buf,
+    size_t size )
+{
+    size_t rv = status->write( status->ctx, buf, size );
+    status->i       += rv;
+    status->current += rv;
+    return rv == size;
+}
+
+/* repeated output of a single character */
+static inline bool cbrept(
+    struct _PDCLIB_status_t * status,
+    char c,
+    size_t times )
+{
+    if ( sizeof(size_t) == 8 && CHAR_BIT == 8)
+    {
+        uint64_t spread = UINT64_C(0x0101010101010101) * c;
+        while ( times )
+        {
+            size_t n = times > 8 ? 8 : times;
+            if ( !cbout( status, &spread, n ) )
+                return false;
+            times -= n;
+        }
+        return true;
+    }
+    else if ( sizeof(size_t) == 4  && CHAR_BIT == 8)
+    {
+        uint32_t spread = UINT32_C(0x01010101) * c;
+        while ( times )
+        {
+            size_t n = times > 4 ? 4 : times;
+            if ( !cbout( status, &spread, n ) )
+                return false;
+            times -= n;
+        }
+        return true;
+    }
+    else
+    {
+        while ( times )
+        {
+            if ( !cbout( status, &c, 1) )
+                return false;
+            times--;
+        }
+        return true;
+    }
+}
+
+
+/* Maximum number of output characters =
+ *   number of bits in (u)intmax_t / number of bits per character in smallest
  *   base. Smallest base is octal, 3 bits/char.
  *
  * Additionally require 2 extra characters for prefixes
  *   base. Smallest base is octal, 3 bits/char.
  *
  * Additionally require 2 extra characters for prefixes
+ *
+ * Returns false if an I/O error occured.
  */
 static const size_t maxIntLen = sizeof(intmax_t) * CHAR_BIT / 3 + 1;
 
  */
 static const size_t maxIntLen = sizeof(intmax_t) * CHAR_BIT / 3 + 1;
 
-static void int2base( uintmax_t value, struct _PDCLIB_status_t * status )
+static bool int2base( uintmax_t value, struct _PDCLIB_status_t * status )
 {
     char sign = 0;
 {
     char sign = 0;
-    if ( ! ( status->flags & E_unsigned ) ) 
+    if ( ! ( status->flags & E_unsigned ) )
     {
         intmax_t signval = (intmax_t) value;
         bool negative = signval < 0;
         value = signval < 0 ? -signval : signval;
 
     {
         intmax_t signval = (intmax_t) value;
         bool negative = signval < 0;
         value = signval < 0 ? -signval : signval;
 
-        if ( negative ) 
+        if ( negative )
         {
             sign = '-';
         {
             sign = '-';
-        } 
-        else if ( status->flags & E_plus ) 
+        }
+        else if ( status->flags & E_plus )
         {
             sign = '+';
         }
         {
             sign = '+';
         }
@@ -98,7 +136,7 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status )
         }
     }
 
         }
     }
 
-    // The user could theoretically ask for a silly buffer length here. 
+    // The user could theoretically ask for a silly buffer length here.
     // Perhaps after a certain size we should malloc? Or do we refuse to protect
     // them from their own stupidity?
     size_t bufLen = (status->width > maxIntLen ? status->width : maxIntLen) + 2;
     // Perhaps after a certain size we should malloc? Or do we refuse to protect
     // them from their own stupidity?
     size_t bufLen = (status->width > maxIntLen ? status->width : maxIntLen) + 2;
@@ -108,7 +146,7 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status )
 
     // Build up our output string - backwards
     {
 
     // Build up our output string - backwards
     {
-        const char * digits = (status->flags & E_lower) ? 
+        const char * digits = (status->flags & E_lower) ?
                                 _PDCLIB_digits : _PDCLIB_Xdigits;
         uintmax_t remaining = value;
         if(status->prec != 0 || remaining != 0) do {
                                 _PDCLIB_digits : _PDCLIB_Xdigits;
         uintmax_t remaining = value;
         if(status->prec != 0 || remaining != 0) do {
@@ -125,9 +163,9 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status )
     // If a field width specified, and zero padding was requested, then pad to
     // the field width
     unsigned padding = 0;
     // If a field width specified, and zero padding was requested, then pad to
     // the field width
     unsigned padding = 0;
-    if ( ( ! ( status->flags & E_minus ) ) && ( status->flags & E_zero ) )    
+    if ( ( ! ( status->flags & E_minus ) ) && ( status->flags & E_zero ) )
     {
     {
-        while( written < (int) status->width ) 
+        while( written < (int) status->width )
         {
             outend[-++written] = '0';
             padding++;
         {
             outend[-++written] = '0';
             padding++;
@@ -167,77 +205,88 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status )
     }
 
     // Write output
     }
 
     // Write output
-    status->current = written;
-    while ( written )
-        PUT( outend[-written--] );
+    return cbout( status, outend - written, written );
 }
 
 }
 
-static void printstr( const char * str, struct _PDCLIB_status_t * status )
+/* print a string. returns false if an I/O error occured */
+static bool printstr( const char * str, struct _PDCLIB_status_t * status )
 {
 {
+    size_t len = status->prec >= 0 ? strnlen( str, status-> prec)
+                                   : strlen(str);
+
     if ( status->width == 0 || status->flags & E_minus )
     {
         // Simple case or left justification
     if ( status->width == 0 || status->flags & E_minus )
     {
         // Simple case or left justification
-        while ( str[status->current] && 
-            ( status->prec < 0 || (long)status->current < status->prec ) )
+        if ( status->prec > 0 )
         {
         {
-            PUT( str[status->current++] );
+            len = (unsigned) status->prec < len ? (unsigned)  status->prec : len;
         }
 
         }
 
-        while( status->current < status->width ) 
-        {
-            PUT( ' ' );
-            status->current++;
+        if ( !cbout( status, str, len ) )
+            return false;
+
+        /* right padding */
+        if ( status->width > status->current ) {
+            len = status->width - status->current;
+
+            if ( !cbrept( status, ' ', len ) )
+                return false;
         }
     } else {
         // Right justification
         }
     } else {
         // Right justification
-        size_t len = status->prec >= 0 ? strnlen( str, status->prec ) 
-                                       :  strlen( str );
-        int padding = status->width - len;
-        while((long)status->current < padding)
-        {
-            PUT( ' ' );
-            status->current++;
-        }
 
 
-        for( size_t i = 0; i != len; i++ )
-        {
-            PUT( str[i] );
-            status->current++;
+        if ( status->width > len ) {
+            size_t padding = status->width - len;
+
+            if ( !cbrept( status, ' ', padding ))
+                return false;
         }
         }
+
+        if ( !cbout( status, str, len ) )
+            return false;
     }
     }
+
+    return true;
 }
 
 }
 
-static void printchar( char chr, struct _PDCLIB_status_t * status )
+static bool printchar( char chr, struct _PDCLIB_status_t * status )
 {
     if( ! ( status->flags & E_minus ) )
     {
         // Right justification
 {
     if( ! ( status->flags & E_minus ) )
     {
         // Right justification
-        for( ; status->current + 1 < status->width; status->current++)
-        {
-            PUT( ' ' );
+        if ( status-> width ) {
+            size_t justification = status->width - status->current - 1;
+            if ( !cbrept( status, ' ', justification ))
+                return false;
         }
         }
-        PUT( chr );
-        status->current++;
+
+        if ( !cbout( status, &chr, 1 ))
+            return false;
     } else {
         // Left justification
     } else {
         // Left justification
-        PUT( chr );
-        status->current++;
 
 
-        for( ; status->current < status->width; status->current++)
-        {
-            PUT( ' ' );
+        if ( !cbout( status, &chr, 1 ))
+            return false;
+
+        if ( status->width > status->current ) {
+            if ( !cbrept( status, ' ', status->width - status->current ) )
+                return false;
         }
     }
         }
     }
+
+    return true;
 }
 
 }
 
-const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status )
+int _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status )
 {
     const char * orig_spec = spec;
     if ( *(++spec) == '%' )
     {
         /* %% -> print single '%' */
 {
     const char * orig_spec = spec;
     if ( *(++spec) == '%' )
     {
         /* %% -> print single '%' */
-        PUT( *spec );
-        return ++spec;
+        if ( !cbout(status, spec, 1) )
+            return -1;
+        ++spec;
+        return (spec - orig_spec);
     }
     /* Initializing status structure */
     status->flags = 0;
     }
     /* Initializing status structure */
     status->flags = 0;
@@ -419,14 +468,18 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status
             break;
         case 'c':
             /* TODO: wide chars. */
             break;
         case 'c':
             /* TODO: wide chars. */
-            printchar( va_arg( status->arg, int ), status );
-            return ++spec;
+            if ( !printchar( va_arg( status->arg, int ), status ) )
+                return -1;
+            ++spec;
+            return (spec - orig_spec);
         case 's':
             /* TODO: wide chars. */
             {
                 char * s = va_arg( status->arg, char * );
         case 's':
             /* TODO: wide chars. */
             {
                 char * s = va_arg( status->arg, char * );
-                printstr( s, status );
-                return ++spec;
+                if ( !printstr( s, status ) )
+                    return -1;
+                ++spec;
+                return (spec - orig_spec);
             }
         case 'p':
             status->base = 16;
             }
         case 'p':
             status->base = 16;
@@ -436,11 +489,12 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status
            {
                int * val = va_arg( status->arg, int * );
                *val = status->i;
            {
                int * val = va_arg( status->arg, int * );
                *val = status->i;
-               return ++spec;
+               ++spec;
+               return (spec - orig_spec);
            }
         default:
             /* No conversion specifier. Bad conversion. */
            }
         default:
             /* No conversion specifier. Bad conversion. */
-            return orig_spec;
+            return 0;
     }
     /* Do the actual output based on our findings */
     if ( status->base != 0 )
     }
     /* Do the actual output based on our findings */
     if ( status->base != 0 )
@@ -479,55 +533,55 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status
                 case E_intmax:
                     value = va_arg( status->arg, uintmax_t );
             }
                 case E_intmax:
                     value = va_arg( status->arg, uintmax_t );
             }
-            int2base( value, status );
+            if ( !int2base( value, status ) )
+                return -1;
         }
         else
         {
         }
         else
         {
+            intmax_t value;
             switch ( status->flags & E_TYPES )
             {
                 case E_char:
             switch ( status->flags & E_TYPES )
             {
                 case E_char:
-                    int2base( (intmax_t)(char)va_arg( status->arg, int ), status );
+                    value = (intmax_t)(char)va_arg( status->arg, int );
                     break;
                 case E_short:
                     break;
                 case E_short:
-                    int2base( (intmax_t)(short)va_arg( status->arg, int ), status );
+                    value = (intmax_t)(short)va_arg( status->arg, int );
                     break;
                 case 0:
                     break;
                 case 0:
-                    int2base( (intmax_t)va_arg( status->arg, int ), status );
+                    value = (intmax_t)va_arg( status->arg, int );
                     break;
                 case E_long:
                     break;
                 case E_long:
-                    int2base( (intmax_t)va_arg( status->arg, long ), status );
+                    value = (intmax_t)va_arg( status->arg, long );
                     break;
                 case E_llong:
                     break;
                 case E_llong:
-                    int2base( (intmax_t)va_arg( status->arg, long long ), status );
+                    value = (intmax_t)va_arg( status->arg, long long );
                     break;
                 case E_size:
                     break;
                 case E_size:
-                    int2base( (intmax_t)va_arg( status->arg, size_t ), status );
+                    value = (intmax_t)va_arg( status->arg, size_t );
                     break;
                 case E_intptr:
                     break;
                 case E_intptr:
-                    int2base( (intmax_t)va_arg( status->arg, intptr_t ), status );
+                    value = (intmax_t)va_arg( status->arg, intptr_t );
                     break;
                 case E_ptrdiff:
                     break;
                 case E_ptrdiff:
-                    int2base( (intmax_t)va_arg( status->arg, ptrdiff_t ), status );
+                    value = (intmax_t)va_arg( status->arg, ptrdiff_t );
                     break;
                 case E_intmax:
                     break;
                 case E_intmax:
-                    int2base( va_arg( status->arg, intmax_t ), status );
+                    value = va_arg( status->arg, intmax_t );
                     break;
             }
                     break;
             }
+
+            if (!int2base( value, status ) )
+                return -1;
         }
         }
-        if ( status->flags & E_minus )
-        {
-            while ( status->current < status->width )
-            {
-                PUT( ' ' );
-                ++(status->current);
-            }
-        }
-        if ( status->i >= status->n && status->n > 0 )
+
+        if ( status->flags & E_minus && status->current < status->width )
         {
         {
-            status->s[status->n - 1] = '\0';
+            if (!cbrept( status, ' ', status->width - status->current ))
+                return -1;
         }
     }
         }
     }
-    return ++spec;
+    ++spec;
+    return spec - orig_spec;
 }
 
 #endif
 }
 
 #endif
@@ -539,22 +593,30 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status
 #include <_PDCLIB_test.h>
 
 #ifndef REGTEST
 #include <_PDCLIB_test.h>
 
 #ifndef REGTEST
+static size_t testcb( void *p, const char *buf, size_t size )
+{
+    char **destbuf = p;
+    memcpy(*destbuf, buf, size);
+    *destbuf += size;
+    return size;
+}
+
 static int testprintf( char * buffer, const char * format, ... )
 {
 static int testprintf( char * buffer, const char * format, ... )
 {
-    /* Members: base, flags, n, i, current, s, width, prec, stream, arg      */
+    /* Members: base, flags, n, i, current, width, prec, ctx, cb, arg      */
     struct _PDCLIB_status_t status;
     status.base = 0;
     status.flags = 0;
     status.n = 100;
     status.i = 0;
     status.current = 0;
     struct _PDCLIB_status_t status;
     status.base = 0;
     status.flags = 0;
     status.n = 100;
     status.i = 0;
     status.current = 0;
-    status.s = buffer;
     status.width = 0;
     status.prec = 0;
     status.width = 0;
     status.prec = 0;
-    status.stream = NULL;
+    status.ctx = &buffer;
+    status.write = testcb;
     va_start( status.arg, format );
     memset( buffer, '\0', 100 );
     va_start( status.arg, format );
     memset( buffer, '\0', 100 );
-    if ( *(_PDCLIB_print( format, &status )) != '\0' )
+    if ( _PDCLIB_print( format, &status ) != strlen( format ) )
     {
         printf( "_PDCLIB_print() did not return end-of-specifier on '%s'.\n", format );
         ++TEST_RESULTS;
     {
         printf( "_PDCLIB_print() did not return end-of-specifier on '%s'.\n", format );
         ++TEST_RESULTS;
index 615d82e0f32ee659d5c9756ac90781b62f9cc660..6a31ff0692dbb8cce0743f0cf624869cd74e7599 100644 (file)
@@ -287,7 +287,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status )
         case 's':
         {
             char * c = va_arg( status->arg, char * );
         case 's':
         {
             char * c = va_arg( status->arg, char * );
-            while ( ( status->current < status->width ) && 
+            while ( ( status->current < status->width ) &&
                     ( ( rc = GET( status ) ) != EOF ) )
             {
                 if ( isspace( rc ) )
                     ( ( rc = GET( status ) ) != EOF ) )
             {
                 if ( isspace( rc ) )
@@ -347,7 +347,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status )
             } while ( *endspec != ']' );
             // read according to scanlist, equiv. to %s above
             char * c = va_arg( status->arg, char * );
             } while ( *endspec != ']' );
             // read according to scanlist, equiv. to %s above
             char * c = va_arg( status->arg, char * );
-            while ( ( status->current < status->width ) && 
+            while ( ( status->current < status->width ) &&
                     ( ( rc = GET( status ) ) != EOF ) )
             {
                 if ( negative_scanlist )
                     ( ( rc = GET( status ) ) != EOF ) )
             {
                 if ( negative_scanlist )
diff --git a/functions/stdio/_cbprintf.c b/functions/stdio/_cbprintf.c
new file mode 100644 (file)
index 0000000..c0192fe
--- /dev/null
@@ -0,0 +1,56 @@
+/* _cbprintf( void *, size_t (*)( void*, const char *, size_t ), 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>
+#include <stdint.h>
+#include <stdarg.h>
+
+#ifndef REGTEST
+
+int _cbprintf(
+    void * p,
+    size_t (*cb)( void*, const char*, size_t ),
+    const char * _PDCLIB_restrict format,
+    ...)
+{
+    int rc;
+    va_list ap;
+    va_start( ap, format );
+    rc = _vcbprintf( p, cb, format, ap );
+    va_end( ap );
+    return rc;
+}
+
+#endif
+
+#ifdef TEST
+#define _PDCLIB_FILEID "stdio/sprintf.c"
+#define _PDCLIB_STRINGIO
+#include <stddef.h>
+
+#include <_PDCLIB_test.h>
+
+static char * bufptr;
+static size_t testcb( void *p, const char *buf, size_t size )
+{
+    memcpy(bufptr, buf, size);
+    bufptr += size;
+    *bufptr = '\0';
+    return size;
+}
+
+#define testprintf( s, ... ) _cbprintf( bufptr = s, testcb, __VA_ARGS__ )
+
+int main( void )
+{
+    char target[100];
+#ifndef REGTEST
+#include "printf_testcases.h"
+#endif
+    return TEST_RESULTS;
+}
+
+#endif
diff --git a/functions/stdio/_vcbprintf.c b/functions/stdio/_vcbprintf.c
new file mode 100644 (file)
index 0000000..dbb2171
--- /dev/null
@@ -0,0 +1,126 @@
+/* $Id$ */
+
+/* vsnprintf( char *, size_t, const char *, va_list ap )
+
+   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>
+#include <stdbool.h>
+
+#ifndef REGTEST
+#include <_PDCLIB_io.h>
+
+/* returns true if callback-based output succeeded; else false */
+static inline bool cbout(
+    struct _PDCLIB_status_t * status,
+    const char *buf,
+    size_t size )
+{
+    size_t rv = status->write( status->ctx, buf, size );
+    status->i += rv;
+    return rv == size;
+}
+
+int _vcbprintf(
+    void *p,
+    size_t ( *cb ) ( void *p, const char *buf, size_t size ),
+    const char *format,
+    va_list arg )
+{
+    struct _PDCLIB_status_t status;
+    status.base     = 0;
+    status.flags    = 0;
+    status.n        = 0;
+    status.i        = 0;
+    status.current  = 0;
+    status.width    = 0;
+    status.prec     = 0;
+    status.ctx      = p;
+    status.write    = cb;
+    va_copy( status.arg, arg );
+
+    /* Alternate between outputing runs of verbatim text and conversions */
+    while ( *format != '\0' )
+    {
+        const char *mark = format;
+        while ( *format != '\0' && *format != '%')
+        {
+            format++;
+        }
+
+        if ( mark != format )
+        {
+            if ( !cbout(&status, mark, format - mark) )
+                return -1;
+        }
+
+        if ( *format == '%' ) {
+            int consumed = _PDCLIB_print( format, &status );
+            if ( consumed > 0 )
+            {
+                format += consumed;
+            }
+            else if ( consumed == 0 )
+            {
+                /* not a conversion specifier, print verbatim */
+                if ( !cbout(&status, format++, 1) )
+                    return -1;
+            }
+            else
+            {
+                /* I/O callback error */
+                return -1;
+            }
+        }
+    }
+
+    va_end( status.arg );
+    return status.i;
+}
+
+#endif
+
+#ifdef TEST
+#define _PDCLIB_FILEID "stdio/_vcbprintf.c"
+#define _PDCLIB_STRINGIO
+#include <stdint.h>
+#include <stddef.h>
+#include <_PDCLIB_test.h>
+
+#ifndef REGTEST
+
+static size_t testcb( void *p, const char *buf, size_t size )
+{
+    char **destbuf = p;
+    memcpy(*destbuf, buf, size);
+    *destbuf += size;
+    return size;
+}
+
+static int testprintf( char * s, const char * format, ... )
+{
+    int i;
+    va_list arg;
+    va_start( arg, format );
+    i = _vcbprintf( &s, testcb, format, arg );
+    *s = 0;
+    va_end( arg );
+    return i;
+}
+
+#endif
+
+int main( void )
+{
+    char target[100];
+#ifndef REGTEST
+#include "printf_testcases.h"
+#endif
+    return TEST_RESULTS;
+}
+
+#endif
+
index 7dd7f2dfe1e6b4855c99b2217e063fce91ebf1da..0aa66485e7ec96b86a5bde2c340a5e214b5de6b6 100644 (file)
 #ifndef REGTEST
 #include <_PDCLIB_io.h>
 
 #ifndef REGTEST
 #include <_PDCLIB_io.h>
 
-int _PDCLIB_vfprintf_unlocked( FILE * _PDCLIB_restrict stream, 
-                       const char * _PDCLIB_restrict format, 
-                       va_list arg )
+static size_t filecb(void *p, const char *buf, size_t size)
 {
 {
-    /* TODO: This function should interpret format as multibyte characters.  */
-    struct _PDCLIB_status_t status;
-    status.base = 0;
-    status.flags = 0;
-    status.n = UINT_MAX;
-    status.i = 0;
-    status.current = 0;
-    status.s = NULL;
-    status.width = 0;
-    status.prec = 0;
-    status.stream = stream;
-    va_copy( status.arg, arg );
+    return _PDCLIB_fwrite_unlocked( buf, 1, size, (FILE*) p );
+}
 
 
-    while ( *format != '\0' )
-    {
-        const char * rc;
-        if ( ( *format != '%' ) || ( ( rc = _PDCLIB_print( format, &status ) ) == format ) )
-        {
-            /* No conversion specifier, print verbatim */
-            _PDCLIB_putc_unlocked( *(format++), stream );
-            status.i++;
-        }
-        else
-        {
-            /* Continue parsing after conversion specifier */
-            format = rc;
-        }
-    }
-    va_end( status.arg );
-    return status.i;
+int _PDCLIB_vfprintf_unlocked( FILE * _PDCLIB_restrict stream,
+                       const char * _PDCLIB_restrict format,
+                       va_list arg )
+{
+    return _vcbprintf(stream, filecb, format, arg);
 }
 
 }
 
-int vfprintf( FILE * _PDCLIB_restrict stream, 
-              const char * _PDCLIB_restrict format, 
+int vfprintf( FILE * _PDCLIB_restrict stream,
+              const char * _PDCLIB_restrict format,
               va_list arg )
 {
     _PDCLIB_flockfile( stream );
               va_list arg )
 {
     _PDCLIB_flockfile( stream );
index 3e4ada482a1e8074aeef459312485b4cfe87c476..148c828fa52898de7a86ea0a8d78a1a40a83e4a3 100644 (file)
@@ -12,7 +12,7 @@
 #ifndef REGTEST
 #include <_PDCLIB_io.h>
 
 #ifndef REGTEST
 #include <_PDCLIB_io.h>
 
-int _PDCLIB_vscanf_unlocked( const char * _PDCLIB_restrict format, 
+int _PDCLIB_vscanf_unlocked( const char * _PDCLIB_restrict format,
                              _PDCLIB_va_list arg )
 {
     return _PDCLIB_vfscanf_unlocked( stdin, format, arg );
                              _PDCLIB_va_list arg )
 {
     return _PDCLIB_vfscanf_unlocked( stdin, format, arg );
index cda7ab6579d4f45ef9d47580fb5ef540e070d094..6cc233d97f4bed54e2cea64b20ac092734f2c163 100644 (file)
 
 #ifndef REGTEST
 #include <_PDCLIB_io.h>
 
 #ifndef REGTEST
 #include <_PDCLIB_io.h>
+#include <string.h>
 
 
-int vsnprintf( char * _PDCLIB_restrict s, 
-               size_t n, 
-               const char * _PDCLIB_restrict format, 
-               _PDCLIB_va_list arg )
+struct state {
+    size_t bufrem;
+    char *bufp;
+};
+
+static size_t strout( void *p, const char *buf, size_t sz )
 {
 {
-    /* TODO: This function should interpret format as multibyte characters.  */
-    struct _PDCLIB_status_t status;
-    status.base = 0;
-    status.flags = 0;
-    status.n = n;
-    status.i = 0;
-    status.current = 0;
-    status.s = s;
-    status.width = 0;
-    status.prec = 0;
-    status.stream = NULL;
-    va_copy( status.arg, arg );
+    struct state *s = p;
+    size_t copy = s->bufrem >= sz ? sz : s->bufrem;
+    memcpy( s->bufp, buf, copy );
+    s->bufrem -= copy;
+    s->bufp   += copy;
+    return sz;
+}
 
 
-    while ( *format != '\0' )
-    {
-        const char * rc;
-        if ( ( *format != '%' ) || ( ( rc = _PDCLIB_print( format, &status ) ) == format ) )
-        {
-            /* No conversion specifier, print verbatim */
-            if ( status.i < n )
-            {
-                s[ status.i ] = *format;
-            }
-            status.i++;
-            format++;
-        }
-        else
-        {
-            /* Continue parsing after conversion specifier */
-            format = rc;
-        }
-    }
-    if ( status.i  < n )
+int vsnprintf( char * _PDCLIB_restrict s,
+               size_t n,
+               const char * _PDCLIB_restrict format,
+               _PDCLIB_va_list arg )
+{
+    struct state st;
+    st.bufrem = n;
+    st.bufp   = s;
+    int r = _vcbprintf( &st, strout, format, arg );
+    if ( st.bufrem )
     {
     {
-        s[ status.i ] = '\0';
+        *st.bufp = 0;
     }
     }
-    va_end( status.arg );
-    return status.i;
+
+    return r;
 }
 
 #endif
 }
 
 #endif
index b10891ffe9b23a7191effab0432ba4bb9fccb5f9..e6e178e0056c5a0fe3907cc3c45364f779226ebf 100644 (file)
@@ -36,7 +36,7 @@ typedef _PDCLIB_file_t FILE;
 #define L_tmpnam _PDCLIB_L_tmpnam
 #define TMP_MAX _PDCLIB_TMP_MAX
 
 #define L_tmpnam _PDCLIB_L_tmpnam
 #define TMP_MAX _PDCLIB_TMP_MAX
 
-/* See fseek(), third argument 
+/* See fseek(), third argument
  *
  * Some system headers (e.g. windows) also define the SEEK_* values. Check for
  * this and validate that they're the same value
  *
  * Some system headers (e.g. windows) also define the SEEK_* values. Check for
  * this and validate that they're the same value
@@ -74,7 +74,7 @@ extern FILE * stderr;
 int remove( const char * filename ) _PDCLIB_nothrow;
 
 /* Rename the given old file to the given new name.
 int remove( const char * filename ) _PDCLIB_nothrow;
 
 /* Rename the given old file to the given new name.
-   Returns zero if successful, non-zero otherwise. 
+   Returns zero if successful, non-zero otherwise.
    This implementation does detect if the old filename corresponds to an open
    file, and fails the rename in this case.
    If there already is a file with the new filename, behaviour is defined by
    This implementation does detect if the old filename corresponds to an open
    file, and fails the rename in this case.
    If there already is a file with the new filename, behaviour is defined by
@@ -171,13 +171,13 @@ int fflush( FILE * stream ) _PDCLIB_nothrow;
 
    Returns a pointer to the stream handle if successfull, NULL otherwise.
 */
 
    Returns a pointer to the stream handle if successfull, NULL otherwise.
 */
-FILE * fopen( const char * _PDCLIB_restrict filename, 
+FILE * fopen( const char * _PDCLIB_restrict filename,
               const char * _PDCLIB_restrict mode ) _PDCLIB_nothrow;
 
 /* Creates a stream connected to the file descriptor \p fd with mode \p mode.
    Mode must match the mode with which the file descriptor was opened.
 */
               const char * _PDCLIB_restrict mode ) _PDCLIB_nothrow;
 
 /* Creates a stream connected to the file descriptor \p fd with mode \p mode.
    Mode must match the mode with which the file descriptor was opened.
 */
-FILE * _PDCLIB_fvopen( _PDCLIB_fd_t fd, const _PDCLIB_fileops_t * ops, 
+FILE * _PDCLIB_fvopen( _PDCLIB_fd_t fd, const _PDCLIB_fileops_t * ops,
                        int mode, const char * filename ) _PDCLIB_nothrow;
 
 /* Close any file currently associated with the given stream. Open the file
                        int mode, const char * filename ) _PDCLIB_nothrow;
 
 /* Close any file currently associated with the given stream. Open the file
@@ -691,7 +691,7 @@ int getchar( void ) _PDCLIB_nothrow;
    and NULL is returned. If a read error occurs, the contents of s are indeter-
    minate, and NULL is returned.
 
    and NULL is returned. If a read error occurs, the contents of s are indeter-
    minate, and NULL is returned.
 
-   This function is dangerous and has been a great source of security 
+   This function is dangerous and has been a great source of security
    vulnerabilities. Do not use it. It was removed by C11.
 */
 char * gets( char * s ) _PDCLIB_DEPRECATED _PDCLIB_nothrow;
    vulnerabilities. Do not use it. It was removed by C11.
 */
 char * gets( char * s ) _PDCLIB_DEPRECATED _PDCLIB_nothrow;
@@ -823,7 +823,7 @@ int ferror( FILE * stream ) _PDCLIB_nothrow;
 */
 void perror( const char * s ) _PDCLIB_nothrow;
 
 */
 void perror( const char * s ) _PDCLIB_nothrow;
 
-/* Unlocked I/O 
+/* Unlocked I/O
  *
  * Since threading was introduced in C11, FILE objects have had implicit locks
  * to prevent data races and inconsistent output.
  *
  * Since threading was introduced in C11, FILE objects have had implicit locks
  * to prevent data races and inconsistent output.
@@ -835,7 +835,7 @@ void perror( const char * s ) _PDCLIB_nothrow;
  * the behaviour of the _unlocked variant is the same except that it will not
  * take the lock associated with the stream.
  *
  * the behaviour of the _unlocked variant is the same except that it will not
  * take the lock associated with the stream.
  *
- * flockfile, ftrylockfile and funlockfile can be used to manually manipulate 
+ * flockfile, ftrylockfile and funlockfile can be used to manually manipulate
  * the stream locks. The behaviour of the _unlocked functions if called when the
  * stream isn't locked by the calling thread is implementation defined.
  */
  * the stream locks. The behaviour of the _unlocked functions if called when the
  * stream isn't locked by the calling thread is implementation defined.
  */
@@ -851,7 +851,7 @@ int putchar_unlocked(int c) _PDCLIB_nothrow;
 #endif
 
 #if _PDCLIB_BSD_SOURCE || _PDCLIB_SVID_SOURCE
 #endif
 
 #if _PDCLIB_BSD_SOURCE || _PDCLIB_SVID_SOURCE
-void clearerr_unlocked(FILE *stream) _PDCLIB_nothrow; 
+void clearerr_unlocked(FILE *stream) _PDCLIB_nothrow;
 int feof_unlocked(FILE *stream) _PDCLIB_nothrow;
 int ferror_unlocked(FILE *stream) _PDCLIB_nothrow;
 int fflush_unlocked(FILE *stream) _PDCLIB_nothrow;
 int feof_unlocked(FILE *stream) _PDCLIB_nothrow;
 int ferror_unlocked(FILE *stream) _PDCLIB_nothrow;
 int fflush_unlocked(FILE *stream) _PDCLIB_nothrow;
@@ -866,7 +866,19 @@ char *fgets_unlocked(char *s, int n, FILE *stream) _PDCLIB_nothrow;
 int fputs_unlocked(const char *s, FILE *stream) _PDCLIB_nothrow;
 #endif
 
 int fputs_unlocked(const char *s, FILE *stream) _PDCLIB_nothrow;
 #endif
 
-#if defined(_PDCLIB_EXTENSIONS)
+#if _PDCLIB_EXTENSIONS
+int _vcbprintf(
+    void *p,
+    _PDCLIB_size_t ( *cb ) ( void *p, const char *buf, _PDCLIB_size_t size ),
+    const char *format,
+    _PDCLIB_va_list arg );
+
+int _cbprintf(
+    void *p,
+    size_t ( *cb ) ( void *p, const char *buf, size_t size ),
+    const char *format,
+    ... );
+
 int fgetpos_unlocked( FILE * _PDCLIB_restrict stream, fpos_t * _PDCLIB_restrict pos ) _PDCLIB_nothrow;
 int fsetpos_unlocked( FILE * stream, const fpos_t * pos ) _PDCLIB_nothrow;
 long int ftell_unlocked( FILE * stream ) _PDCLIB_nothrow;
 int fgetpos_unlocked( FILE * _PDCLIB_restrict stream, fpos_t * _PDCLIB_restrict pos ) _PDCLIB_nothrow;
 int fsetpos_unlocked( FILE * stream, const fpos_t * pos ) _PDCLIB_nothrow;
 long int ftell_unlocked( FILE * stream ) _PDCLIB_nothrow;
index 134123a1862fa650a1bccb0be8bb8186c8f638fd..c200419e6133a0235fd92448066744cdf83db6d6 100644 (file)
@@ -338,13 +338,13 @@ typedef struct _PDCLIB_mbstate {
      */
     _PDCLIB_uint16_t     _Surrogate;
 
      */
     _PDCLIB_uint16_t     _Surrogate;
 
-    /* In cases where the underlying codec is capable of regurgitating a 
+    /* In cases where the underlying codec is capable of regurgitating a
      * character without consuming any extra input (e.g. a surrogate pair in a
      * character without consuming any extra input (e.g. a surrogate pair in a
-     * UCS-4 to UTF-16 conversion) then these fields are used to track that 
+     * UCS-4 to UTF-16 conversion) then these fields are used to track that
      * state. In particular, they are used to buffer/fake the input for mbrtowc
      * and similar functions.
      *
      * state. In particular, they are used to buffer/fake the input for mbrtowc
      * and similar functions.
      *
-     * See _PDCLIB_encoding.h for values of _PendState and the resultant value 
+     * See _PDCLIB_encoding.h for values of _PendState and the resultant value
      * in _PendChar.
      */
     unsigned char _PendState;
      * in _PendChar.
      */
     unsigned char _PendState;
@@ -375,17 +375,26 @@ typedef struct _PDCLIB_file     _PDCLIB_file_t; // Rename to _PDCLIB_FILE?
 /* Status structure required by _PDCLIB_print(). */
 struct _PDCLIB_status_t
 {
 /* Status structure required by _PDCLIB_print(). */
 struct _PDCLIB_status_t
 {
+    /* XXX This structure is horrible now. scanf needs its own */
+
     int              base;   /* base to which the value shall be converted   */
     _PDCLIB_int_fast32_t flags; /* flags and length modifiers                */
     int              base;   /* base to which the value shall be converted   */
     _PDCLIB_int_fast32_t flags; /* flags and length modifiers                */
-    unsigned         n;      /* print: maximum characters to be written      */
+    unsigned         n;      /* print: maximum characters to be written (snprintf) */
                              /* scan:  number matched conversion specifiers  */
     unsigned         i;      /* number of characters read/written            */
     unsigned         current;/* chars read/written in the CURRENT conversion */
                              /* scan:  number matched conversion specifiers  */
     unsigned         i;      /* number of characters read/written            */
     unsigned         current;/* chars read/written in the CURRENT conversion */
-    char *           s;      /* *sprintf(): target buffer                    */
-                             /* *sscanf():  source string                    */
     unsigned         width;  /* specified field width                        */
     int              prec;   /* specified field precision                    */
     unsigned         width;  /* specified field width                        */
     int              prec;   /* specified field precision                    */
-    _PDCLIB_file_t * stream; /* *fprintf() / *fscanf() stream         */
+
+    union {
+        void *           ctx;    /* context for callback */
+        const char *     s;      /* input string for scanf */
+    };
+
+    union {
+        _PDCLIB_size_t ( *write ) ( void *p, const char *buf, _PDCLIB_size_t size );
+        _PDCLIB_file_t *stream;  /* for scanf */
+    };
     _PDCLIB_va_list  arg;    /* argument stack                               */
 };
 
     _PDCLIB_va_list  arg;    /* argument stack                               */
 };
 
index 65b658901ca1293f1cf51d41102aa7b2db74e93d..78e747c0edcc1df81a8184ca7a74372f4ef90a5a 100644 (file)
@@ -53,9 +53,10 @@ union _PDCLIB_fd
    be that of the current printf() function, of which the members n, s, stream\r
    and arg will be preserved; i will be updated; and all others will be trashed\r
    by the function.\r
    be that of the current printf() function, of which the members n, s, stream\r
    and arg will be preserved; i will be updated; and all others will be trashed\r
    by the function.\r
-   Returns a pointer to the first character not parsed as conversion specifier.\r
+   Returns the number of characters parsed as a conversion specifier (0 if none\r
+   parsed); returns -1 if the underlying I/O callback returns failure.\r
 */\r
 */\r
-const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status );\r
+int _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status );\r
 \r
 /* The worker for all scanf() type of functions. The pointer spec should point\r
    to the introducing '%' of a conversion specifier. The status structure is to\r
 \r
 /* The worker for all scanf() type of functions. The pointer spec should point\r
    to the introducing '%' of a conversion specifier. The status structure is to\r
@@ -71,7 +72,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status )
 /* Parsing any fopen() style filemode string into a number of flags. */\r
 unsigned int _PDCLIB_filemode( const char * mode );\r
 \r
 /* Parsing any fopen() style filemode string into a number of flags. */\r
 unsigned int _PDCLIB_filemode( const char * mode );\r
 \r
-/* Sanity checking and preparing of read buffer, should be called first thing \r
+/* Sanity checking and preparing of read buffer, should be called first thing\r
    by any stdio read-data function.\r
    Returns 0 on success, EOF on error.\r
    On error, EOF / error flags and errno are set appropriately.\r
    by any stdio read-data function.\r
    Returns 0 on success, EOF on error.\r
    On error, EOF / error flags and errno are set appropriately.\r
@@ -103,7 +104,7 @@ int _PDCLIB_fillbuffer( _PDCLIB_file_t * stream );
 /* Repositions within a file. Returns new offset on success,\r
    -1 / errno on error.\r
 */\r
 /* Repositions within a file. Returns new offset on success,\r
    -1 / errno on error.\r
 */\r
-_PDCLIB_int_fast64_t _PDCLIB_seek( _PDCLIB_file_t * stream, \r
+_PDCLIB_int_fast64_t _PDCLIB_seek( _PDCLIB_file_t * stream,\r
                                   _PDCLIB_int_fast64_t offset, int whence );\r
 \r
 /* File backend I/O operations\r
                                   _PDCLIB_int_fast64_t offset, int whence );\r
 \r
 /* File backend I/O operations\r
@@ -122,49 +123,49 @@ struct _PDCLIB_fileops
      *  On error, returns false and sets errno appropriately. *numBytesRead is\r
      *  ignored in this situation.\r
      */\r
      *  On error, returns false and sets errno appropriately. *numBytesRead is\r
      *  ignored in this situation.\r
      */\r
-    _PDCLIB_bool (*read)( _PDCLIB_fd_t self, \r
-                          void * buf, \r
-                          _PDCLIB_size_t length, \r
+    _PDCLIB_bool (*read)( _PDCLIB_fd_t self,\r
+                          void * buf,\r
+                          _PDCLIB_size_t length,\r
                           _PDCLIB_size_t * numBytesRead );\r
 \r
     /*! Write length bytes to the file from buf; returning the number of bytes\r
      *  actually written in *numBytesWritten\r
      *\r
      *  Returns true if bytes were written successfully. On error, returns false\r
                           _PDCLIB_size_t * numBytesRead );\r
 \r
     /*! Write length bytes to the file from buf; returning the number of bytes\r
      *  actually written in *numBytesWritten\r
      *\r
      *  Returns true if bytes were written successfully. On error, returns false\r
-     *  and setss errno appropriately (as with read, *numBytesWritten is \r
+     *  and setss errno appropriately (as with read, *numBytesWritten is\r
      *  ignored)\r
      */\r
      *  ignored)\r
      */\r
-    _PDCLIB_bool (*write)( _PDCLIB_fd_t self, const void * buf, \r
+    _PDCLIB_bool (*write)( _PDCLIB_fd_t self, const void * buf,\r
                    _PDCLIB_size_t length, _PDCLIB_size_t * numBytesWritten );\r
 \r
     /* Seek to the file offset specified by offset, from location whence, which\r
      * may be one of the standard constants SEEK_SET/SEEK_CUR/SEEK_END\r
      */\r
                    _PDCLIB_size_t length, _PDCLIB_size_t * numBytesWritten );\r
 \r
     /* Seek to the file offset specified by offset, from location whence, which\r
      * may be one of the standard constants SEEK_SET/SEEK_CUR/SEEK_END\r
      */\r
-    _PDCLIB_bool (*seek)( _PDCLIB_fd_t self, _PDCLIB_int_fast64_t offset, \r
+    _PDCLIB_bool (*seek)( _PDCLIB_fd_t self, _PDCLIB_int_fast64_t offset,\r
                           int whence, _PDCLIB_int_fast64_t *newPos );\r
 \r
     void (*close)( _PDCLIB_fd_t self );\r
 \r
                           int whence, _PDCLIB_int_fast64_t *newPos );\r
 \r
     void (*close)( _PDCLIB_fd_t self );\r
 \r
-    /*! Behaves as read does, except for wide characters. Both length and \r
+    /*! Behaves as read does, except for wide characters. Both length and\r
      *  *numCharsRead represent counts of characters, not bytes.\r
      *\r
      *  This function is optional; if missing, PDCLib will buffer the character\r
      *  data as bytes and perform translation directly into the user's buffers.\r
      *  *numCharsRead represent counts of characters, not bytes.\r
      *\r
      *  This function is optional; if missing, PDCLib will buffer the character\r
      *  data as bytes and perform translation directly into the user's buffers.\r
-     *  It is useful if your backend can directly take wide characters (for \r
+     *  It is useful if your backend can directly take wide characters (for\r
      *  example, the Windows console)\r
      */\r
      *  example, the Windows console)\r
      */\r
-    _PDCLIB_bool (*wread)( _PDCLIB_fd_t self, _PDCLIB_wchar_t * buf, \r
+    _PDCLIB_bool (*wread)( _PDCLIB_fd_t self, _PDCLIB_wchar_t * buf,\r
                      _PDCLIB_size_t length, _PDCLIB_size_t * numCharsRead );\r
 \r
     /* Behaves as write does, except for wide characters. As with wread, both\r
      * length and *numCharsWritten are character counts.\r
      *\r
                      _PDCLIB_size_t length, _PDCLIB_size_t * numCharsRead );\r
 \r
     /* Behaves as write does, except for wide characters. As with wread, both\r
      * length and *numCharsWritten are character counts.\r
      *\r
-     * This function is also optional; if missing, PDCLib will buffer the \r
-     * character data as bytes and do translation directly from the user's \r
-     * buffers. You only need to implement this if your backend can directly \r
+     * This function is also optional; if missing, PDCLib will buffer the\r
+     * character data as bytes and do translation directly from the user's\r
+     * buffers. You only need to implement this if your backend can directly\r
      * take wide characters (for example, the Windows console)\r
      */\r
      * take wide characters (for example, the Windows console)\r
      */\r
-    _PDCLIB_bool (*wwrite)( _PDCLIB_fd_t self, const _PDCLIB_wchar_t * buf, \r
+    _PDCLIB_bool (*wwrite)( _PDCLIB_fd_t self, const _PDCLIB_wchar_t * buf,\r
                      _PDCLIB_size_t length, _PDCLIB_size_t * numCharsWritten );\r
 };\r
 \r
                      _PDCLIB_size_t length, _PDCLIB_size_t * numCharsWritten );\r
 };\r
 \r
@@ -195,7 +196,7 @@ static inline _PDCLIB_size_t _PDCLIB_getchars( char * out, _PDCLIB_size_t n,
     int c;\r
     while ( stream->ungetidx > 0 && i != n )\r
     {\r
     int c;\r
     while ( stream->ungetidx > 0 && i != n )\r
     {\r
-        c = (unsigned char) \r
+        c = (unsigned char)\r
                 ( out[ i++ ] = stream->ungetbuf[ --(stream->ungetidx) ] );\r
         if( c == stopchar )\r
             return i;\r
                 ( out[ i++ ] = stream->ungetbuf[ --(stream->ungetidx) ] );\r
         if( c == stopchar )\r
             return i;\r
@@ -203,9 +204,9 @@ static inline _PDCLIB_size_t _PDCLIB_getchars( char * out, _PDCLIB_size_t n,
 \r
     while ( i != n )\r
     {\r
 \r
     while ( i != n )\r
     {\r
-        while ( stream->bufidx != stream->bufend && i != n) \r
+        while ( stream->bufidx != stream->bufend && i != n)\r
         {\r
         {\r
-            c = (unsigned char) \r
+            c = (unsigned char)\r
                 ( out[ i++ ] = stream->buffer[ stream->bufidx++ ] );\r
             if( c == stopchar )\r
                 return i;\r
                 ( out[ i++ ] = stream->buffer[ stream->bufidx++ ] );\r
             if( c == stopchar )\r
                 return i;\r
@@ -223,10 +224,10 @@ static inline _PDCLIB_size_t _PDCLIB_getchars( char * out, _PDCLIB_size_t n,
     return i;\r
 }\r
 \r
     return i;\r
 }\r
 \r
-/* Unlocked functions - internal names \r
+/* Unlocked functions - internal names\r
  *\r
  * We can't use the functions using their "normal" names internally because that\r
  *\r
  * We can't use the functions using their "normal" names internally because that\r
- * would cause namespace leakage. Therefore, we use them by prefixed internal \r
+ * would cause namespace leakage. Therefore, we use them by prefixed internal\r
  * names\r
  */\r
 void _PDCLIB_flockfile(struct _PDCLIB_file *file) _PDCLIB_nothrow;\r
  * names\r
  */\r
 void _PDCLIB_flockfile(struct _PDCLIB_file *file) _PDCLIB_nothrow;\r
@@ -237,7 +238,7 @@ int _PDCLIB_getc_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;
 int _PDCLIB_getchar_unlocked(void) _PDCLIB_nothrow;\r
 int _PDCLIB_putc_unlocked(int c, struct _PDCLIB_file *stream) _PDCLIB_nothrow;\r
 int _PDCLIB_putchar_unlocked(int c) _PDCLIB_nothrow;\r
 int _PDCLIB_getchar_unlocked(void) _PDCLIB_nothrow;\r
 int _PDCLIB_putc_unlocked(int c, struct _PDCLIB_file *stream) _PDCLIB_nothrow;\r
 int _PDCLIB_putchar_unlocked(int c) _PDCLIB_nothrow;\r
-void _PDCLIB_clearerr_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow; \r
+void _PDCLIB_clearerr_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;\r
 int _PDCLIB_feof_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;\r
 int _PDCLIB_ferror_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;\r
 int _PDCLIB_fflush_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;\r
 int _PDCLIB_feof_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;\r
 int _PDCLIB_ferror_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;\r
 int _PDCLIB_fflush_unlocked(struct _PDCLIB_file *stream) _PDCLIB_nothrow;\r