]> pd.if.org Git - pdclib/blobdiff - functions/_PDCLIB/print.c
Clearing the Tyndur tests.
[pdclib] / functions / _PDCLIB / print.c
index d2b5dbddc41c29dc895d4e3d17621df31c37fd05..6db55e85a27307ef8211091f2891148f69c0ed3f 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stddef.h>
+#include <string.h>
 
 #ifndef REGTEST
 
@@ -158,6 +159,12 @@ static void intformat( intmax_t value, struct _PDCLIB_status_t * status )
 */
 static void int2base( intmax_t value, struct _PDCLIB_status_t * status )
 {
+    /* Special case: zero value, zero precision -- no output (but padding) */
+    if ( status->current == 0 && value == 0 && status->prec == 0 )
+    {
+        intformat( value, status );
+        return;
+    }
     /* 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.
@@ -198,6 +205,55 @@ static void int2base( intmax_t value, struct _PDCLIB_status_t * status )
 }
 
 
+static void stringformat( const char * s, struct _PDCLIB_status_t * status )
+{
+    if ( status->flags & E_char )
+    {
+        status->prec = 1;
+    }
+    else
+    {
+        if ( status->prec < 0 )
+        {
+            status->prec = strlen( s );
+        }
+        else
+        {
+            for ( int i = 0; i < status->prec; ++i )
+            {
+                if ( s[i] == 0 )
+                {
+                    status->prec = i;
+                    break;
+                }
+            }
+        }
+    }
+    if ( ! ( status->flags & E_minus ) && ( status->width > (_PDCLIB_size_t)status->prec ) )
+    {
+        while ( status->current < ( status->width - status->prec ) )
+        {
+            PUT( ' ' );
+            ++(status->current);
+        }
+    }
+    while ( status->prec > 0 )
+    {
+        PUT( *(s++) );
+        --(status->prec);
+        ++(status->current);
+    }
+    if ( status->flags & E_minus )
+    {
+        while ( status->width > status->current )
+        {
+            PUT( ' ' );
+            ++(status->current);
+        }
+    }
+}
+
+
 const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status )
 {
     const char * orig_spec = spec;
@@ -393,21 +449,19 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status
         case 'A':
             break;
         case 'c':
-            /* TODO: Flags, wide chars. */
-            PUT( va_arg( status->arg, int ) );
-            return ++spec;
-        case 's':
-            /* TODO: Flags, wide chars. */
+            /* TODO: wide chars. */
             {
-                char * s = va_arg( status->arg, char * );
-                while ( *s != '\0' )
-                {
-                    PUT( *(s++) );
-                }
+                char c[1];
+                c[0] = (char)va_arg( status->arg, int );
+                status->flags |= E_char;
+                stringformat( c, status );
                 return ++spec;
             }
+        case 's':
+            /* TODO: wide chars. */
+            stringformat( va_arg( status->arg, char * ), status );
+            return ++spec;
         case 'p':
-            /* TODO: E_long -> E_intptr */
             status->base = 16;
             status->flags |= ( E_lower | E_unsigned | E_alt | E_pointer );
             break;
@@ -457,28 +511,39 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status
                     puts( "UNSUPPORTED PRINTF FLAG COMBINATION" );
                     return NULL;
             }
-            ++(status->current);
-            if ( ( value / status->base ) != 0 )
+            /* Special case: zero value, zero precision: No output, just padding */
+            if ( value == 0 && status->prec == 0 )
             {
-                /* Get value to "safe" levels re. uintmax_t. */
-                int2base( (intmax_t)(value / status->base), status );
+                int2base( 0, status );
             }
             else
             {
-                intformat( (intmax_t)value, status );
-            }
-            int digit = value % status->base;
-            if ( digit < 0 )
-            {
-                digit *= -1;
-            }
-            if ( status->flags & E_lower )
-            {
-                PUT( _PDCLIB_digits[ digit ] );
-            }
-            else
-            {
-                PUT( _PDCLIB_Xdigits[ digit ] );
+                /* To make the call to int2base (using intmax_t) safe for
+                   uintmax_t values > INTMAX_MAX, we basically to the first
+                   "recursion" level of int2base right here.
+                */
+                ++(status->current);
+                if ( ( value / status->base ) != 0 )
+                {
+                    int2base( (intmax_t)(value / status->base), status );
+                }
+                else
+                {
+                    intformat( (intmax_t)value, status );
+                }
+                int digit = value % status->base;
+                if ( digit < 0 )
+                {
+                    digit *= -1;
+                }
+                if ( status->flags & E_lower )
+                {
+                    PUT( _PDCLIB_digits[ digit ] );
+                }
+                else
+                {
+                    PUT( _PDCLIB_Xdigits[ digit ] );
+                }
             }
         }
         else
@@ -548,7 +613,7 @@ static int testprintf( char * buffer, const char * format, ... )
     status.current = 0;
     status.s = buffer;
     status.width = 0;
-    status.prec = 0;
+    status.prec = EOF;
     status.stream = NULL;
     va_start( status.arg, format );
     memset( buffer, '\0', 100 );