Reworked scanf() testing. General cleanups.
[fw/pdclib] / functions / stdio / vfscanf.c
1 /* $Id$ */
2
3 /* vfscanf( FILE *, const char *, va_list )
4
5    This file is part of the Public Domain C Library (PDCLib).
6    Permission is granted to use, modify, and / or redistribute at will.
7 */
8
9 #include <stdio.h>
10 #include <stdarg.h>
11 #include <ctype.h>
12
13 #ifndef REGTEST
14
15 int vfscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, va_list arg )
16 {
17     /* TODO: This function should interpret format as multibyte characters.  */
18     struct _PDCLIB_status_t status;
19     status.base = 0;
20     status.flags = 0;
21     status.n = 0;
22     status.i = 0;
23     status.current = 0;
24     status.s = NULL;
25     status.width = 0;
26     status.prec = 0;
27     status.stream = stream;
28     va_copy( status.arg, arg );
29
30     while ( *format != '\0' )
31     {
32         const char * rc;
33         if ( ( *format != '%' ) || ( ( rc = _PDCLIB_scan( format, &status ) ) == format ) )
34         {
35             int c;
36             /* No conversion specifier, match verbatim */
37             if ( isspace( *format ) )
38             {
39                 /* Whitespace char in format string: Skip all whitespaces */
40                 /* No whitespaces in input does not result in matching error */
41                 while ( isspace( c = getc( stream ) ) )
42                 {
43                     ++status.i;
44                 }
45                 if ( ! feof( stream ) ) /* TODO: Check EOF status directly */
46                 {
47                     ungetc( c, stream );
48                 }
49             }
50             else
51             {
52                 /* Non-whitespace char in format string: Match verbatim */
53                 if ( ( ( c = getc( stream ) ) != *format ) || feof( stream ) ) /* TODO: Check EOF status directly */
54                 {
55                     /* Matching error */
56                     if ( ! feof( stream ) && ! ferror( stream ) ) /* TODO: Check EOF status directly */
57                     {
58                         ungetc( c, stream );
59                     }
60                     else if ( status.n == 0 )
61                     {
62                         return EOF;
63                     }
64                     return status.n;
65                 }
66                 else
67                 {
68                     ++status.i;
69                 }
70             }
71             ++format;
72         }
73         else
74         {
75             /* NULL return code indicates matching error */
76             if ( rc == NULL )
77             {
78                 break;
79             }
80             /* Continue parsing after conversion specifier */
81             format = rc;
82         }
83     }
84     va_end( status.arg );
85     return status.n;
86 }
87
88 #endif
89
90 #ifdef TEST
91 #define _PDCLIB_FILEID "stdio/vfscanf.c"
92 #define _PDCLIB_FILEIO
93
94 #include <_PDCLIB_test.h>
95
96 static int testscanf( FILE * stream, char const * format, ... )
97 {
98     va_list ap;
99     va_start( ap, format );
100     int result = vfscanf( stream, format, ap );
101     va_end( ap );
102     return result;
103 }
104
105 int main( void )
106 {
107     FILE * source;
108     TESTCASE( ( source = tmpfile() ) != NULL );
109 #include "scanf_testcases.h"
110     TESTCASE( fclose( source ) == 0 );
111     return TEST_RESULTS;
112 }
113
114 #endif
115