]> pd.if.org Git - pdclib/blobdiff - functions/_PDCLIB/print.c
Fix warnings
[pdclib] / functions / _PDCLIB / print.c
index 439098d69bc604331de9b5e832178fb431c4c32a..95fbe9c752e62acd964b2f5c981e3c6e2d7d56da 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
+#include <string.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdbool.h>
 /* FIXME: one too many flags to work on a 16-bit machine, join some (e.g. the
           width flags) into a combined field.
 */
-#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_ldouble  1<<14
-#define E_lower    1<<15
-#define E_unsigned 1<<16
+#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_ldouble  (1<<14)
+#define E_lower    (1<<15)
+#define E_unsigned (1<<16)
 
 /* This macro delivers a given character to either a memory buffer or a stream,
    depending on the contents of 'status' (struct _PDCLIB_status_t).
@@ -52,7 +53,7 @@ do { \
     int character = x; \
     if ( status->i < status->n ) { \
         if ( status->stream != NULL ) \
-            putc( character, status->stream ); \
+            putc_unlocked( character, status->stream ); \
         else \
             status->s[status->i] = character; \
     } \
@@ -96,14 +97,14 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status )
     size_t bufLen = (status->width > maxIntLen ? status->width : maxIntLen) + 2;
     char outbuf[bufLen];
     char * outend = outbuf + bufLen;
-    unsigned written = 0;
+    int written = 0;
 
     // Build up our output string - backwards
     {
         const char * digits = (status->flags & E_lower) ? 
                                 _PDCLIB_digits : _PDCLIB_Xdigits;
         uintmax_t remaining = value;
-        do {
+        if(status->prec != 0 || remaining != 0) do {
             uintmax_t digit = remaining % status->base;
             remaining /= status->base;
 
@@ -119,7 +120,7 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status )
     unsigned padding = 0;
     if ( ( ! ( status->flags & E_minus ) ) && ( status->flags & E_zero ) )    
     {
-        while( written < status->width ) 
+        while( written < (int) status->width ) 
         {
             outend[-++written] = '0';
             padding++;
@@ -155,7 +156,7 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status )
     // Space padding to field width
     if ( ! ( status->flags & ( E_minus | E_zero ) ) )
     {
-        while( written < status->width ) outend[-++written] = ' ';
+        while( written < (int) status->width ) outend[-++written] = ' ';
     }
 
     // Write output
@@ -164,6 +165,64 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status )
         PUT( outend[-written--] );
 }
 
+static void printstr( const char * str, struct _PDCLIB_status_t * status )
+{
+    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 ) )
+        {
+            PUT( str[status->current++] );
+        }
+
+        while( status->current < status->width ) 
+        {
+            PUT( ' ' );
+            status->current++;
+        }
+    } 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++;
+        }
+    }
+}
+
+static void printchar( char chr, struct _PDCLIB_status_t * status )
+{
+    if( ! ( status->flags & E_minus ) )
+    {
+        // Right justification
+        for( ; status->current + 1 < status->width; status->current++)
+        {
+            PUT( ' ' );
+        }
+        PUT( chr );
+        status->current++;
+    } else {
+        // Left justification
+        PUT( chr );
+        status->current++;
+
+        for( ; status->current < status->width; status->current++)
+        {
+            PUT( ' ' );
+        }
+    }
+}
+
 const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status )
 {
     const char * orig_spec = spec;
@@ -253,20 +312,14 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status
                EOF (negative), there is no need for testing for negative here.
             */
             status->prec = va_arg( status->arg, int );
+            ++spec;
         }
         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;
+            status->prec = (int)strtol( spec, (char**) &spec, 10 );
         }
         /* Having a precision cancels out any zero flag. */
-        status->flags ^= E_zero;
+        status->flags &= ~E_zero;
     }
 
     /* Optional length modifier
@@ -358,17 +411,14 @@ 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 ) );
+            /* TODO: wide chars. */
+            printchar( va_arg( status->arg, int ), status );
             return ++spec;
         case 's':
-            /* TODO: Flags, wide chars. */
+            /* TODO: wide chars. */
             {
                 char * s = va_arg( status->arg, char * );
-                while ( *s != '\0' )
-                {
-                    PUT( *(s++) );
-                }
+                printstr( s, status );
                 return ++spec;
             }
         case 'p':