From: solar Date: Mon, 14 Sep 2009 05:25:57 +0000 (+0000) Subject: First work towards scanf(). X-Git-Tag: v0.5~124 X-Git-Url: https://pd.if.org/git/?p=pdclib;a=commitdiff_plain;h=68525aefa7b7b1f2f769e287e1f2f3a4585005ff First work towards scanf(). --- diff --git a/Makefile b/Makefile index 7750bf2..e9ba02e 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ SRCFILES := $(shell find $(PROJDIRS) -mindepth 1 -maxdepth 3 -name "*.c") # All header files of the project HDRFILES := $(shell find $(PROJDIRS) -mindepth 1 -maxdepth 3 -name "*.h") # All .c files in functions/_PDCLIB that do not have a regression test driver -INTFILES := _Exit atomax digits open print remove rename seed stdinit strtox_main strtox_prelim cleanstream fflush filemode eol errno seek prepread prepwrite +INTFILES := _Exit atomax digits open print scan remove rename seed stdinit strtox_main strtox_prelim cleanstream fflush filemode eol errno seek prepread prepwrite # All object files in the library OBJFILES := $(patsubst %.c,%.o,$(SRCFILES)) # All test drivers (.t) diff --git a/functions/_PDCLIB/scan.c b/functions/_PDCLIB/scan.c new file mode 100644 index 0000000..d12e884 --- /dev/null +++ b/functions/_PDCLIB/scan.c @@ -0,0 +1,25 @@ +/* $Id$ */ + +/* _PDCLIB_scan( const char *, struct _PDCLIB_status_t * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ) +{ + return ++spec; +} + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} + +#endif diff --git a/functions/stdio/vsscanf.c b/functions/stdio/vsscanf.c index 75f334d..c4565aa 100644 --- a/functions/stdio/vsscanf.c +++ b/functions/stdio/vsscanf.c @@ -13,8 +13,64 @@ int vsscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, va_list arg ) { - /* TODO: Implement. */ - return 0; + struct _PDCLIB_status_t status; + status.base = 0; + status.flags = 0; + /* In _PDCLIB_print, status.n holds the maximum number of characters to be + written. As we don't need that for the scanf() functions, we (ab)use + this field to hold the number of matching conversion specifiers. + */ + status.n = 0; + status.i = 0; + status.this = 0; + /* In _PDCLIB_print, status.s is the string *printed to*. In the scanf() + functions, we (ab)use this field to hold the string *scanned from*. + */ + status.s = (char *)s; + status.width = 0; + status.prec = 0; + status.stream = NULL; + va_copy( status.arg, arg ); + while ( *format != '\0' ) + { + const char * rc; + if ( ( *format != '%' ) || ( ( rc = _PDCLIB_scan( format, &status ) ) == format ) ) + { + /* No conversion specifier, match verbatim */ + if ( isspace( *format ) ) + { + /* Whitespace char in format string: Skip all whitespaces */ + /* No whitespaces in input do not result in matching error */ + while ( isspace( *status.s ) ) + { + ++status.s; + ++status.i; + } + } + else + { + /* Non-whitespace char in format string: Match verbatim */ + if ( *status.s != *format ) + { + /* Matching error */ + return status.n; + } + else + { + ++status.s; + ++status.i; + } + } + ++format; + } + else + { + /* Continue parsing after conversion specifier */ + format = rc; + } + } + va_end( status.arg ); + return status.n; } #endif @@ -24,7 +80,18 @@ int vsscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict form int main( void ) { - TESTCASE( NO_TESTDRIVER ); + char const * teststring1 = "abc def"; + char const * teststring2 = "abcdef"; + char const * teststring3 = "abc%def"; + int x; + TESTCASE( sscanf( teststring2, "abcdef%n", &x ) == 0 ); + TESTCASE( x == 6 ); + TESTCASE( sscanf( teststring1, "abc def%n", &x ) == 0 ); + TESTCASE( x == 8 ); + TESTCASE( sscanf( teststring2, "abc def%n", &x ) == 0 ); + TESTCASE( x == 6 ); + TESTCASE( sscanf( teststring3, "abc%%def%n", &x ) == 0 ); + TESTCASE( x == 7 ); return TEST_RESULTS; } diff --git a/internals/_PDCLIB_int.h b/internals/_PDCLIB_int.h index 02e122e..62c38b2 100644 --- a/internals/_PDCLIB_int.h +++ b/internals/_PDCLIB_int.h @@ -345,12 +345,21 @@ extern char _PDCLIB_Xdigits[]; /* The worker for all printf() type of functions. The pointer spec should point to the introducing '%' of a conversion specifier. The status structure is to be that of the current printf() function, of which the members n, s, stream - and arg will be preserved, i will be updated, and all others will be trashed + and arg will be preserved; i will be updated; and all others will be trashed by the function. Returns a pointer to the first character not parsed as conversion specifier. */ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status ); +/* The worker for all scanf() type of functions. The pointer spec should point + to the introducing '%' of a conversion specifier. The status structure is to + be that of the current scanf() function, of which the member stream will be + preserved, n, i, and s will be updated; and all others will be trashed by the + function. + Returns a pointer to the first character not parsed as conversion specifier. +*/ +const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ); + /* Parsing any fopen() style filemode string into a number of flags. */ unsigned int _PDCLIB_filemode( const char * mode );