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