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