3 /* _PDCLIB_scan( const char *, struct _PDCLIB_status_t * )
5 This file is part of the Public Domain C Library (PDCLib).
6 Permission is granted to use, modify, and / or redistribute at will.
15 /* Using an integer's bits as flags for both the conversion flags and length
18 #define E_suppressed 1<<0
23 #define E_intmax 1<<10
25 #define E_ptrdiff 1<<12
26 #define E_intptr 1<<13
27 #define E_ldouble 1<<14
28 #define E_unsigned 1<<16
32 #define MATCH_ERROR -2
34 static int MATCH( int c, struct _PDCLIB_status_t * status )
36 if ( status->stream != NULL )
38 if ( ! _PDCLIB_prepread( status->stream ) )
42 if ( tolower( status->stream->buffer[ status->stream->bufidx ] ) == c )
44 /* recycling parameter */
45 c = getc( status->stream );
54 if ( tolower( *(status->s) ) == c )
56 /* recycling parameter */
57 c = *((status->s)++); /* TODO: \0 */
70 static void UNGET( int c, struct _PDCLIB_status_t * status )
72 if ( status->stream != NULL )
74 ungetc( c, status->stream ); /* TODO: Error? */
85 const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status )
87 const char * orig_spec = spec;
88 if ( *(++spec) == '%' )
90 /* %% -> match single '%' */
91 MATCH( *spec, status );
94 /* Initializing status structure */
101 /* '*' suppresses assigning parsed value to variable */
104 status->flags |= E_suppressed;
108 /* If a width is given, strtol() will return its value. If not given,
109 strtol() will return zero. In both cases, endptr will point to the
110 rest of the conversion specifier - just what we need.
112 status->width = (int)strtol( spec, (char**)&spec, 10 );
114 /* Optional length modifier
115 We step one character ahead in any case, and step back only if we find
116 there has been no length modifier (or step ahead another character if it
117 has been "hh" or "ll").
125 status->flags |= E_char;
131 status->flags |= E_short;
137 /* ll -> long long */
138 status->flags |= E_llong;
144 status->flags |= E_long;
148 /* j -> intmax_t, which might or might not be long long */
149 status->flags |= E_intmax;
152 /* z -> size_t, which might or might not be unsigned int */
153 status->flags |= E_size;
156 /* t -> ptrdiff_t, which might or might not be long */
157 status->flags |= E_ptrdiff;
160 /* L -> long double */
161 status->flags |= E_ldouble;
168 /* Conversion specifier */
179 status->flags |= E_unsigned;
183 status->flags |= E_unsigned;
187 status->flags |= E_unsigned;
207 status->flags |= E_unsigned;
211 int * val = va_arg( status->arg, int * );
216 /* No conversion specifier. Bad conversion. */
220 if ( status->base != -1 )
224 if ( ( rc = MATCH( '0', status ) ) >= 0 )
226 if ( ( rc = MATCH( 'x', status ) ) >= 0 )
228 if ( ( status->base == 0 ) || ( status->base == 16 ) )
238 else if ( rc == MATCH_FAIL )
240 if ( status->base == 0 )
251 /* TODO: MATCH_ERROR */
254 else if ( rc == MATCH_FAIL )
256 if ( status->base == 0 )
263 /* TODO: MATCH_ERROR */
265 /* TODO: Integer conversion */
269 /* TODO: Float conversions? */
275 #include <_PDCLIB_test.h>
279 TESTCASE( NO_TESTDRIVER );