X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=functions%2F_PDCLIB%2Fscan.c;h=dc94e7fc25856aa2576f3cab66d17a7889bb7e13;hb=b1fc26afebd4d557ff89a44bc21767a8704c3809;hp=b346ffc2bb81dc7943d1db696e168241e2a77370;hpb=a7a8d2f1c85c2d7760d4d3479e90466cc3a81b04;p=pdclib diff --git a/functions/_PDCLIB/scan.c b/functions/_PDCLIB/scan.c index b346ffc..dc94e7f 100644 --- a/functions/_PDCLIB/scan.c +++ b/functions/_PDCLIB/scan.c @@ -1,5 +1,3 @@ -/* $Id$ */ - /* _PDCLIB_scan( const char *, struct _PDCLIB_status_t * ) This file is part of the Public Domain C Library (PDCLib). @@ -32,18 +30,6 @@ #define E_unsigned 1<<16 -/* Helper macro for assigning a readily converted integer value to the correct - parameter type, used in a switch on status->flags (see E_* flags above). - case_cond: combination of the E_* flags above, used for the switch-case - type: integer type, used to get the correct type from the parameter - stack as well as for cast target. -*/ -#define ASSIGN_VALUE_TO( case_cond, type ) \ - case case_cond: \ - *( va_arg( status->arg, type * ) ) = (type)( value * sign ); \ - break - - /* Helper function to get a character from the string or stream, whatever is used for input. When reading from a string, returns EOF on end-of-string so that handling of the return value can be uniform for both streams and @@ -51,7 +37,7 @@ */ static int GET( struct _PDCLIB_status_t * status ) { - int rc; + int rc = EOF; if ( status->stream != NULL ) { rc = getc( status->stream ); @@ -531,31 +517,70 @@ 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 ) ) { - ASSIGN_VALUE_TO( E_char, char ); - ASSIGN_VALUE_TO( E_char | E_unsigned, unsigned char ); - ASSIGN_VALUE_TO( E_short, short ); - ASSIGN_VALUE_TO( E_short | E_unsigned, unsigned short ); - ASSIGN_VALUE_TO( 0, int ); - ASSIGN_VALUE_TO( E_unsigned, unsigned int ); - ASSIGN_VALUE_TO( E_long, long ); - ASSIGN_VALUE_TO( E_long | E_unsigned, unsigned long ); - ASSIGN_VALUE_TO( E_llong, long long ); - ASSIGN_VALUE_TO( E_llong | E_unsigned, unsigned long long ); - ASSIGN_VALUE_TO( E_intmax, intmax_t ); - ASSIGN_VALUE_TO( E_intmax | E_unsigned, uintmax_t ); - ASSIGN_VALUE_TO( E_size, size_t ); - /* ASSIGN_VALUE_TO( E_size | E_unsigned, unsigned size_t ); */ - ASSIGN_VALUE_TO( E_ptrdiff, ptrdiff_t ); - /* ASSIGN_VALUE_TO( E_ptrdiff | E_unsigned, unsigned ptrdiff_t ); */ - default: - puts( "UNSUPPORTED SCANF FLAG COMBINATION" ); - return NULL; /* behaviour unspecified */ + switch ( status->flags & ( E_char | E_short | E_long | E_llong | + E_intmax | E_size | E_ptrdiff | + 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 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_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_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; + + default: + puts( "UNSUPPORTED SCANF FLAG COMBINATION" ); + return NULL; /* behaviour unspecified */ + } + ++(status->n); } - ++(status->n); return ++spec; } /* TODO: Floats. */