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