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