]> pd.if.org Git - pdclib/blobdiff - functions/_PDCLIB/scan.c
Fixed pointer handling of printf() / scanf().
[pdclib] / functions / _PDCLIB / scan.c
index 6bef32ec54ceb6b56cb6a27dc4419ec5248fa870..8d4d7e0b98b3de5db39ff07fd71c83cadefb68cd 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 /* _PDCLIB_scan( const char *, struct _PDCLIB_status_t * )
 
    This file is part of the Public Domain C Library (PDCLib).
@@ -27,7 +25,7 @@
 #define E_intmax     1<<10
 #define E_size       1<<11
 #define E_ptrdiff    1<<12
-#define E_intptr     1<<13
+#define E_pointer    1<<13
 #define E_ldouble    1<<14
 #define E_unsigned   1<<16
 
@@ -39,7 +37,7 @@
 */
 static int GET( struct _PDCLIB_status_t * status )
 {
-    int rc;
+    int rc = EOF;
     if ( status->stream != NULL )
     {
         rc = getc( status->stream );
@@ -285,7 +283,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status )
         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 ) )
@@ -345,7 +343,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 ( ( status->current < status->width ) && 
+            while ( ( status->current < status->width ) &&
                     ( ( rc = GET( status ) ) != EOF ) )
             {
                 if ( negative_scanlist )
@@ -384,7 +382,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status )
         }
         case 'p':
             status->base = 16;
-            status->flags |= E_unsigned;
+            status->flags |= E_pointer;
             break;
         case 'n':
         {
@@ -519,67 +517,75 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status )
             return NULL;
         }
         /* convert value to target type and assign to parameter */
-        switch ( status->flags & ( E_char | E_short | E_long | E_llong |
-                                   E_intmax | E_size | E_ptrdiff |
-                                   E_unsigned ) )
+        if ( ! ( status->flags & E_suppressed ) )
         {
-            case E_char:
-                *( va_arg( status->arg,               char * ) ) =               (char)( value * sign );
-                break;
-            case E_char | E_unsigned:
-                *( va_arg( status->arg,      unsigned char * ) ) =      (unsigned char)( value * sign );
-                break;
+            switch ( status->flags & ( E_char | E_short | E_long | E_llong |
+                                       E_intmax | E_size | E_ptrdiff | E_pointer |
+                                       E_unsigned ) )
+            {
+                case E_char:
+                    *( va_arg( status->arg,               char * ) ) =               (char)( value * sign );
+                    break;
+                case E_char | E_unsigned:
+                    *( va_arg( status->arg,      unsigned char * ) ) =      (unsigned char)( value * sign );
+                    break;
 
-            case E_short:
-                *( va_arg( status->arg,              short * ) ) =              (short)( value * sign );
-                break;
-            case E_short | E_unsigned:
-                *( va_arg( status->arg,     unsigned short * ) ) =     (unsigned short)( value * sign );
-                break;
+                case E_short:
+                    *( va_arg( status->arg,              short * ) ) =              (short)( value * sign );
+                    break;
+                case E_short | E_unsigned:
+                    *( va_arg( status->arg,     unsigned short * ) ) =     (unsigned short)( value * sign );
+                    break;
 
-            case 0:
-                *( va_arg( status->arg,                int * ) ) =                (int)( value * sign );
-                break;
-            case E_unsigned:
-                *( va_arg( status->arg,       unsigned int * ) ) =       (unsigned int)( value * sign );
-                break;
+                case 0:
+                    *( va_arg( status->arg,                int * ) ) =                (int)( value * sign );
+                    break;
+                case E_unsigned:
+                    *( va_arg( status->arg,       unsigned int * ) ) =       (unsigned int)( value * sign );
+                    break;
 
-            case E_long:
-                *( va_arg( status->arg,               long * ) ) =               (long)( value * sign );
-                break;
-            case E_long | E_unsigned:
-                *( va_arg( status->arg,      unsigned long * ) ) =      (unsigned long)( value * sign );
-                break;
+                case E_long:
+                    *( va_arg( status->arg,               long * ) ) =               (long)( value * sign );
+                    break;
+                case E_long | E_unsigned:
+                    *( va_arg( status->arg,      unsigned long * ) ) =      (unsigned long)( value * sign );
+                    break;
 
-            case E_llong:
-                *( va_arg( status->arg,          long long * ) ) =          (long long)( value * sign );
-                break;
-            case E_llong | E_unsigned:
-                *( va_arg( status->arg, unsigned long long * ) ) = (unsigned long long)( value * sign );
-                break;
+                case E_llong:
+                    *( va_arg( status->arg,          long long * ) ) =          (long long)( value * sign );
+                    break;
+                case E_llong | E_unsigned:
+                    *( va_arg( status->arg, unsigned long long * ) ) = (unsigned long long)( value * sign );
+                    break;
 
-            case E_intmax:
-                *( va_arg( status->arg,           intmax_t * ) ) =           (intmax_t)( value * sign );
-                break;
-            case E_intmax | E_unsigned:
-                *( va_arg( status->arg,          uintmax_t * ) ) =          (uintmax_t)( value * sign );
-                break;
+                case E_intmax:
+                    *( va_arg( status->arg,           intmax_t * ) ) =           (intmax_t)( value * sign );
+                    break;
+                case E_intmax | E_unsigned:
+                    *( va_arg( status->arg,          uintmax_t * ) ) =          (uintmax_t)( value * sign );
+                    break;
 
-            case E_size:
-                /* E_size always implies unsigned */
-                *( va_arg( status->arg,             size_t * ) ) =             (size_t)( value * sign );
-                break;
+                case E_size:
+                    /* E_size always implies unsigned */
+                    *( va_arg( status->arg,             size_t * ) ) =             (size_t)( value * sign );
+                    break;
 
-            case E_ptrdiff:
-                /* E_ptrdiff always implies signed */
-                *( va_arg( status->arg,          ptrdiff_t * ) ) =          (ptrdiff_t)( value * sign );
-                break;
+                case E_ptrdiff:
+                    /* E_ptrdiff always implies signed */
+                    *( va_arg( status->arg,          ptrdiff_t * ) ) =          (ptrdiff_t)( value * sign );
+                    break;
 
-            default:
-                puts( "UNSUPPORTED SCANF FLAG COMBINATION" );
-                return NULL; /* behaviour unspecified */
+                case E_pointer:
+                    /* E_pointer always implies unsigned */
+                    *( uintptr_t* )( va_arg( status->arg, void * ) ) =          (uintptr_t)( value * sign );
+                    break;
+
+                default:
+                    puts( "UNSUPPORTED SCANF FLAG COMBINATION" );
+                    return NULL; /* behaviour unspecified */
+            }
+            ++(status->n);
         }
-        ++(status->n);
         return ++spec;
     }
     /* TODO: Floats. */