diff --git a/CMakeLists.txt b/CMakeLists.txt index edbea0d..3f809db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,6 +124,7 @@ set(SOURCES src/stdio/fputs.c src/stdio/fread.c src/stdio/freopen.c + src/stdio/fscanf.c src/stdio/fseek.c src/stdio/fsetpos.c src/stdio/ftell.c @@ -145,19 +146,24 @@ set(SOURCES src/stdio/puts.c src/stdio/remove.c src/stdio/rewind.c + src/stdio/scanf.c src/stdio/scanf/scan.c src/stdio/setbuf.c src/stdio/setvbuf.c src/stdio/snprintf.c src/stdio/sprintf.c + src/stdio/sscanf.c src/stdio/streams.c src/stdio/ungetc.c src/stdio/vasprintf.c src/stdio/vdprintf.c src/stdio/vfprintf.c + src/stdio/vfscanf.c src/stdio/vprintf.c + src/stdio/vscanf.c src/stdio/vsnprintf.c src/stdio/vsprintf.c + src/stdio/vsscanf.c # stdlib src/stdlib/abort.c src/stdlib/abs.c diff --git a/src/stdio/stdio_p.h b/include/fxlibc/scanf.h similarity index 60% rename from src/stdio/stdio_p.h rename to include/fxlibc/scanf.h index 150fc22..38c0fee 100644 --- a/src/stdio/stdio_p.h +++ b/include/fxlibc/scanf.h @@ -1,7 +1,14 @@ -#ifndef __STDIO_P_H__ -# define __STDIO_P_H__ +#ifndef __SCANF_H__ +# define __SCANF_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + #include +#include /* ** General utilities for scanf(); we expose them here as we use subfunctions of @@ -16,9 +23,25 @@ struct __scanf_input { char const * __restrict__ str; FILE *fp; + + // max char to read from the input stream as per user length modifier + int readmaxlength; + int currentlength; + + // total number of char read so far in the current call of a XYscanf() function (to return a %n when required) + int readsofar; + int buffer; }; + +/* Generic formatted scaning. */ +extern int __scanf( + struct __scanf_input * __restrict__ __in, + char const * __restrict__ __format, + va_list *__args); + + /* Initialize the input by feeding the buffer byte. */ void __scanf_start(struct __scanf_input *__in); @@ -30,16 +53,27 @@ static inline int __scanf_in(struct __scanf_input *__in) { int c = __in->buffer; __in->buffer = __scanf_fetch(__in); + __in->readsofar++; + __in->currentlength++; return c; } /* Peek the next byte without advancing. */ static inline int __scanf_peek(struct __scanf_input *__in) { - return __in->buffer; + if (__in->readmaxlength==-1 || __in->currentlength<__in->readmaxlength ) + return __in->buffer; + else return 0; } /* Close the input by unsending the buffer once finished. */ void __scanf_end(struct __scanf_input *__in); -#endif /* __STDIO_P_H__ */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* __SCANF_H__ */ diff --git a/src/stdlib/stdlib_p.h b/include/fxlibc/stdlib_p.h similarity index 98% rename from src/stdlib/stdlib_p.h rename to include/fxlibc/stdlib_p.h index c368086..39f60fa 100644 --- a/src/stdlib/stdlib_p.h +++ b/include/fxlibc/stdlib_p.h @@ -3,7 +3,7 @@ #include #include -#include "../stdio/stdio_p.h" +#include /* ** Parse an integer from a string. This is the base function for strtol, diff --git a/src/stdio/fscanf.c b/src/stdio/fscanf.c new file mode 100644 index 0000000..37d90cf --- /dev/null +++ b/src/stdio/fscanf.c @@ -0,0 +1,17 @@ +#include +#include + +int fscanf(FILE * restrict fp, char const * restrict fmt, ...) +{ + struct __scanf_input in = { + .fp = fp, + }; + + va_list args; + va_start(args, fmt); + + int count = __scanf(&in, fmt, &args); + + va_end(args); + return count; +} \ No newline at end of file diff --git a/src/stdio/scanf.c b/src/stdio/scanf.c new file mode 100644 index 0000000..18fd3c5 --- /dev/null +++ b/src/stdio/scanf.c @@ -0,0 +1,17 @@ +#include +#include + +int scanf(char const * restrict fmt, ...) +{ + struct __scanf_input in = { + .fp = stdin, + }; + + va_list args; + va_start(args, fmt); + + int count = __scanf(&in, fmt, &args); + + va_end(args); + return count; +} \ No newline at end of file diff --git a/src/stdio/scanf/scan.c b/src/stdio/scanf/scan.c index 1bc93ee..061582b 100644 --- a/src/stdio/scanf/scan.c +++ b/src/stdio/scanf/scan.c @@ -1,37 +1,669 @@ #include -#include "../stdio_p.h" -#include "../../stdlib/stdlib_p.h" +#include +#include +#include +#include -void __scanf_start(struct __scanf_input *__in) +void __scanf_start(struct __scanf_input *in) { - if(__in->fp) - __in->buffer = fgetc(__in->fp); + if(in->fp) + in->buffer = fgetc(in->fp); else { - __in->buffer = *__in->str; - __in->str += (__in->buffer != 0); + in->buffer = (*in->str ? *in->str : EOF); + in->str += (in->buffer != 0); } } -int __scanf_fetch(struct __scanf_input *__in) +int __scanf_fetch(struct __scanf_input *in) { - if(__in->fp) - return fgetc(__in->fp); + if(in->fp) + return fgetc(in->fp); - int c = *__in->str; + int c = *in->str; if(c == 0) return EOF; - __in->str++; + in->str++; return c; } -void __scanf_end(struct __scanf_input *__in) +void __scanf_end(struct __scanf_input *in) { - if(__in->buffer == EOF) + if(in->buffer == EOF) return; - if(__in->fp) - ungetc(__in->buffer, __in->fp); + if(in->fp) + ungetc(in->buffer, in->fp); else - __in->str--; + in->str--; } + + +enum +{ + MODSKIP, + MODCHAR, + MODSHORT, + MODNORMAL, + MODLONG, + MODLONGLONG, + MODLONGDOUBLE, + MODINTMAXT, + MODSIZET, + MODPTRDIFFT, +}; + +void __purge_space( struct __scanf_input * __restrict__ in ) +{ + while (isspace(__scanf_peek(in))) __scanf_in(in); +} + +void __scanf_store_i(int64_t value, int size, va_list *args) +{ + if(size == MODSKIP) return; + + if(size == MODCHAR) + *va_arg(*args, int8_t *) = value; + else if(size == MODSHORT) + *va_arg(*args, int16_t *) = value; + else if(size == MODLONGLONG) + *va_arg(*args, int64_t *) = value; + else if(size == MODINTMAXT) + *va_arg(*args, intmax_t *) = value; + else if(size == MODSIZET) + *va_arg(*args, size_t *) = value; + else if(size == MODPTRDIFFT) + *va_arg(*args, ptrdiff_t *) = value; + else + *va_arg(*args, int *) = value; +} + +void __scanf_store_d(long double value, int size, va_list *args) +{ + if (size==MODSKIP) return; + + if(size == MODLONG) + *va_arg(*args, double *) = value; + else if(size == MODLONGDOUBLE) + *va_arg(*args, long double *) = value; + else + *va_arg(*args, float *) = value; +} + +/* STATUS OF __scanf DEVELOPMENT */ + +// XX = not done yet (but will be done) +// OK = OK, done and tested +// -- = not applicable +// NO = not supported (and will not be done) only for %lc as long char are not supported by gint + + +/*************************************************************************************************************/ +/* Specifier * Explanation * num * hh * h *none* l * ll * j * z * t * L */ +/*************************************************************************************************************/ +/* % * Parse literal '%' * -- * -- * -- * OK * -- * -- * -- * -- * -- * -- */ +/*************************************************************************************************************/ +/* c * match a char or several char * OK * -- * -- * OK * NO * -- * -- * -- * -- * -- */ +/*************************************************************************************************************/ +/* s * match a string * OK * -- * -- * OK * NO * -- * -- * -- * -- * -- */ +/*************************************************************************************************************/ +/* [set] * match a set of char * OK * -- * -- * OK * -- * -- * -- * -- * -- * -- */ +/*************************************************************************************************************/ +/* d * match a decimal integer * OK * OK * OK * OK * OK * OK * OK * OK * OK * -- */ +/*************************************************************************************************************/ +/* i * match an integer * OK * OK * OK * OK * OK * OK * OK * OK * OK * -- */ +/*************************************************************************************************************/ +/* d * match an unsigned decimal integer * OK * OK * OK * OK * OK * OK * OK * OK * OK * -- */ +/*************************************************************************************************************/ +/* o * match a unsigned octal integer * OK * OK * OK * OK * OK * OK * OK * OK * OK * -- */ +/*************************************************************************************************************/ +/* x,X * match a unsigned hexadecimal integer * OK * OK * OK * OK * OK * OK * OK * OK * OK * -- */ +/*************************************************************************************************************/ +/* n * return the nb of chars read so far * -- * -- * -- * OK * -- * -- * -- * -- * -- * -- */ +/*************************************************************************************************************/ +/* a,A * match a floating point number * OK * -- * -- * OK * OK * -- * -- * -- * -- * OK */ +/* e,E * match a floating point number * OK * -- * -- * OK * OK * -- * -- * -- * -- * OK */ +/* f,F * match a floating point number * OK * -- * -- * OK * OK * -- * -- * -- * -- * OK */ +/* g,G * match a floating point number * OK * -- * -- * OK * OK * -- * -- * -- * -- * OK */ +/*************************************************************************************************************/ +/* p * match a pointer * -- * -- * -- * OK * -- * -- * -- * -- * -- * -- */ +/*************************************************************************************************************/ + +// %ms and %m[set] are not implemented (with memory allocation while parsing a chain or a set of characters) + + +/* list of allowed char given by a set %[], this is updated at every set */ +bool __asciiallowed[256] = { true }; + +/* unallow all the char for the current set */ +void __unallow_all_set( void ) +{ + for(int u =0; u<=255; u++) + __asciiallowed[u]=false; +} + +/* allow all the char for the current set */ +void __allow_all_set( void ) +{ + for(int u =0; u<=255; u++) + __asciiallowed[u]=true; +} + +/* allo a range of char for the current set */ +/* note1 : c1 and c2 do not to be sorted */ +/* note2 : not sur if C standard requires to be ordered or not */ +void __define_set_range( char c1, char c2, bool value ) +{ + char beg = (c1 < c2 ? c1 : c2 ); + char end = (c1 >= c2 ? c1 : c2 ); + + for (int u=beg; u<=end; u++) + __asciiallowed[u] = value; +} + +/* return true if the char is in the allowed set or false otherwise */ +bool __is_allowed( const unsigned char c ) +{ + return __asciiallowed[ c ]; +} + + +/* return 0 if Ok or -1 if syntax err in the set format */ +int __scanset(char const * __restrict__ format, int *pos ) +{ + int __sor = 0; + int __eor = 0; + bool __neg = false; + + __unallow_all_set(); + + (*pos)++; + + // next will be a "negation" set + if (format[*pos] == '^' ) { + __neg = true; + (*pos)++; + __allow_all_set(); + + // the char ']' is part of the set + if (format[*pos] == ']' ) { + __asciiallowed[ ']' ] = !__neg; + (*pos)++; + } + } + // the char ']' is included in the allowed set + else if (format[*pos] == ']' ) { + __neg = false; + // the char ']' is part of the set + if (format[*pos] == ']' ) { + __asciiallowed[ ']' ] = !__neg; + (*pos)++; + } + } + + // start of format analysis loop + loopset: + + // we find a '-' so need to check if we are considering a range or the char '-' only + if (format[*pos]=='-') { + // the char '-' is included in the allowed set + if (format[*pos+1]==']') { + __asciiallowed[ '-' ] = !__neg; // if set in very final position before']', this is the char '-' only + (*pos)++; + // we have now finished the reading of the set cause the following char is ']' + return 0; + } + // the char '-' indicates a range of char to be included into the set + else { + (*pos)++; + __eor = format[*pos]; + __define_set_range( __sor, __eor, !__neg ); + goto loopset; + } + } + // we find the char ']' so it means we reach the end of this set + else if (format[*pos]==']') return 0; + // if we reach the '\0' we have a syntax problem + else if (format[*pos]=='\0') return -1; + // we are considering one particular char and prepare for a potential range if we find the char '-' later on + else { + __sor = format[*pos]; + __asciiallowed[ __sor ] = !__neg; + (*pos)++; + goto loopset; + } +} + + + +int __scanf( + struct __scanf_input * __restrict__ in, + char const * __restrict__ format, + va_list *args) +{ + + bool skip = false; + + int MOD = MODNORMAL; + + in->readsofar = 0; // we haven't started to read char from the input stream + in->readmaxlength = -1; // no specific maximum length to read is defined yet + + int validrets = 0; // to be incremented each time we successfully read and store an input as per the format + int err = 0; // err control on __strto_xx( ) functions + int user_length = 0; // length defined by user with a %xx modifier + int pos = 0; // current pos in the format string + + __scanf_start( in ); + + while( format[pos] != 0 ) { + in->readmaxlength = -1; + user_length = 0; + MOD = MODNORMAL; + skip = false; + + __allow_all_set(); + + if( format[pos] == ' ' ) { + __purge_space(in); + } + // we will have to manage a given format + else if( format[pos] == '%' ) { + + in->readmaxlength = -1; + // main loop + loopagain: + + pos++; + + switch( format[pos] ) { + // we need to decrypt the corresponding scanf set of character + case '[': { + char temp; + err = __scanset( format, &pos ); + if (err!=0) return validrets; + int currentlength = 0; + // we need to assign the read char to the corresponding pointer + if (!skip) { + char *c = (char *) va_arg( *args, char* ); + if (in->readmaxlength==-1) { + for(;;) { + temp = __scanf_peek( in ); + if (temp==EOF) return EOF; + else if (__is_allowed( temp )) { + *c++ = __scanf_in( in ); + currentlength++; + } + else { + if (currentlength>0) { + *c = '\0'; + validrets++; + goto exitset; + } + else return validrets; + } + } + } + else { + for(int u=0; ureadmaxlength; u++) { + temp = __scanf_peek( in ); + if (temp==EOF) return EOF; + else if (__is_allowed( temp )) { + *c++ = __scanf_in( in ); + currentlength++; + } + else { + if (currentlength>0) { + *c = '\0'; + validrets++; + goto exitset; + } + else return validrets; + } + } + if (currentlength>0) { + *c = '\0'; + validrets++; + goto exitset; + } + else return validrets; + } + } + + else + { + if (in->readmaxlength==-1) { + for(;;) { + temp = __scanf_peek( in ); + if (temp==EOF) return EOF; + else if (__is_allowed( temp )) { + __scanf_in( in ); + currentlength++; + } + else if (currentlength>0) goto exitset; + else return validrets; + } + } + else { + for(int u=0; ureadmaxlength; u++) { + temp = __scanf_peek( in ); + if (temp==EOF) return EOF; + else if (__is_allowed( temp )) __scanf_in( in ); + else if (currentlength>0) goto exitset; + else return validrets; + } + } + } + + exitset: + break; + } + + // return the number of char read so far (cannot be skipped %*n is not valid) + case 'n': { + *(int*) va_arg( *args, int* ) = in->readsofar; + break; + } + + // we are expecting the char '%' to be in the input stream, if not err and return + case '%': { + if (__scanf_peek(in) != '%') return validrets; + else __scanf_in( in ); + break; + } + + // the next read, even if valid, will not be stored + case '*': { + skip = true; + goto loopagain; + break; + } + + case 'h': { + if (MOD==MODNORMAL || MOD==MODSHORT) { + MOD--; + goto loopagain; + } + else return validrets; // we cannot have %hhh format modifier --> err + break; + } + + case 'l': { + if (MOD==MODNORMAL || MOD==MODLONG) { + MOD++; + goto loopagain; + } + else return validrets; // we cannot have %ll format modifier --> err + break; + } + + case 'L': { + if (MOD==MODNORMAL) { + MOD=MODLONGDOUBLE; + goto loopagain; + } + else return validrets; // we cannot have %LL format modifier --> err + break; + } + + case 'j': { + if (MOD==MODNORMAL) { + MOD=MODINTMAXT; + goto loopagain; + } + else return validrets; // we cannot have %LL format modifier --> err + break; + } + + case 'z': { + if (MOD==MODNORMAL) { + MOD=MODSIZET; + goto loopagain; + } + else return validrets; // we cannot have %LL format modifier --> err + break; + } + + case 't': { + if (MOD==MODNORMAL) { + MOD=MODPTRDIFFT; + goto loopagain; + } + else return validrets; // we cannot have %LL format modifier --> err + break; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + user_length = user_length * 10 + (int) ( format[pos] - '0' ); + in->readmaxlength = user_length; + goto loopagain; + break; + } + + case 'd': { + // read a long int (in base 10 - decimal) from the current input stream + // and store in the corresponding arg as a char by reference + long long int temp; + err = __strto_int( in, 10, NULL, &temp, false ); // base is 10 as for strtol + if (err != 0) return validrets; + if (skip) __scanf_store_i( temp, MODSKIP, args ); + else __scanf_store_i( temp, MOD, args ); + validrets++; + break; + } + + case 'i': { + // read a signed int (base to be defined at read) from the current input stream + // and store in the corresponding arg as a char by reference + long long int temp; + err = __strto_int( in, 0, NULL, &temp, false ); // base is 0 as for strtol + if (err != 0) return validrets; + if (skip) __scanf_store_i( temp, MODSKIP, args ); + else __scanf_store_i( temp, MOD, args ); + validrets++; + break; + } + + case 'u': { + // read a unsigned int (in base 10 - decimal) from the current input stream + // and store in the corresponding arg as a char by reference + long long int temp; + err = __strto_int( in, 10, NULL, &temp, false ); // base is 10 as for strtol - use_unsigned must be false (validated with glibc6.2 behaviour) + if (err != 0) return validrets; + if (skip) __scanf_store_i( temp, MODSKIP, args ); + else __scanf_store_i( temp, MOD, args ); + validrets++; + break; + } + + case 'o': { + // read a unsigned int (in base 8 - octal) from the current input stream + // and store in the corresponding arg as a char by reference + long long int temp; + err = __strto_int( in, 8, NULL, &temp, true ); // base is 8 as for strtol + if (err != 0) return validrets; + if (skip) __scanf_store_i( temp, MODSKIP, args ); + else __scanf_store_i( temp, MOD, args ); + validrets++; + break; + } + + case 'x': + case 'X': { + // read a unsigned int (in base 16 - hexadecimal) from the current input stream + // and store in the corresponding arg as a char by reference + long long int temp; + err = __strto_int( in, 16, NULL, &temp, true ); // base is 16 as for strtol + if (err != 0) return validrets; + if (skip) __scanf_store_i( temp, MODSKIP, args ); + else __scanf_store_i( temp, MOD, args ); + validrets++; + break; + } + + case 'a': + case 'A': + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': { + // read a double from the current input stream + // and store in the corresponding arg as a char by reference + long double temp; + err = __strto_fp( in, NULL, NULL, &temp ); + if (err != 0) return validrets; + if (skip) __scanf_store_d( temp, MODSKIP, args ); + else __scanf_store_d( temp, MOD, args ); + validrets++; + break; + } + + case 'p': { + long int temp; + if (!skip) { + void *p = (void *) va_arg( *args, void** ); // get the adress of the target pointer (void**) + err = __strto_int( in, 0, p, NULL, true ); + } + else err = __strto_int( in, 0, &temp, NULL, true ); + if (err == 0) validrets++; + else return validrets; + skip = false; + break; + } + + case 'c': { + char temp; + if (!skip) { + char *c = (char *) va_arg( *args, char* ); + if (in->readmaxlength==-1) { + temp = __scanf_peek( in ); + if (temp==EOF) return EOF; + else *c = __scanf_in( in ); + } + else { + for( int u = 0; u < in->readmaxlength; u++ ) { + temp = __scanf_peek( in ); + if (temp==EOF) return EOF; + else *c++ = __scanf_in( in ); + } + } + } + else { + if (in->readmaxlength==-1) { + temp = __scanf_peek( in ); + if (temp==EOF) return EOF; + else { + __scanf_in( in ); + goto endcharskip; + } + } + else { + for( int u = 0; u < in->readmaxlength; u++ ) { + temp = __scanf_peek( in ); + if (temp==EOF) return EOF; + else __scanf_in( in ); + } + goto endcharskip; + } + } + + validrets++; + + endcharskip: + break; + } + + case 's': { + char temp; + int curstrlength = 0; + __purge_space( in ); + if (!skip) { + char *c = (char *) va_arg( *args, char* ); + if (in->readmaxlength==-1) { + loopstring: + temp = __scanf_peek( in ); + if (temp==EOF && curstrlength==0) return validrets; + if (isspace(temp) || ( (temp==EOF && curstrlength!=0) )) { + *c = 0; + goto loopstringend; + } + else { + *c++ = __scanf_in( in ); + curstrlength++; + goto loopstring; + } + } + else { + for( int u = 0; u < in->readmaxlength; u++ ) { + temp = __scanf_peek( in ); + if (temp==EOF && curstrlength==0) return validrets; + if (isspace(temp) || ( (temp==EOF && curstrlength!=0) )) { + *c = 0; + goto loopstringend; + } + else { + *c++ = __scanf_in( in ); + curstrlength++; + } + } + } + } + else { + if (in->readmaxlength==-1) { + loopstringskip: + temp = __scanf_peek( in ); + if (temp==EOF && curstrlength==0) return validrets; + if (isspace(temp) || ( (temp==EOF && curstrlength!=0) )) goto loopstringendskip; + else { + __scanf_in( in ); + curstrlength++; + goto loopstringskip; + } + } + else { + for( int u = 0; u < in->readmaxlength; u++ ) { + temp = __scanf_peek( in ); + if (temp==EOF && curstrlength==0) return validrets; + if (isspace(temp) || ( (temp==EOF && curstrlength!=0) )) goto loopstringendskip; + else { + __scanf_in( in ); + curstrlength++; + } + } + } + } + + loopstringend: + validrets++; + + loopstringendskip: + break; + } + } + } + // we are looking for a specific character in the input stream + else { + // if the next char of the stream is corresponding, we validate the read and go to the following char + if(format[pos] == __scanf_peek( in )) { + __scanf_in( in ); + pos++; + } + else return validrets; // else we return the number of valid read + } + pos++; + } + + __scanf_end( in ); + return validrets; +} \ No newline at end of file diff --git a/src/stdio/sscanf.c b/src/stdio/sscanf.c new file mode 100644 index 0000000..9a7e87f --- /dev/null +++ b/src/stdio/sscanf.c @@ -0,0 +1,18 @@ +#include +#include + +int sscanf(const char * restrict str, char const * restrict fmt, ...) +{ + /* This is valid even if str=NULL. */ + struct __scanf_input in = { + .str = str, + }; + + va_list args; + va_start(args, fmt); + + int count = __scanf(&in, fmt, &args); + + va_end(args); + return count; +} diff --git a/src/stdio/vfscanf.c b/src/stdio/vfscanf.c new file mode 100644 index 0000000..019f94e --- /dev/null +++ b/src/stdio/vfscanf.c @@ -0,0 +1,11 @@ +#include +#include + +int vfscanf(FILE * restrict fp, char const * restrict fmt, va_list args) +{ + struct __scanf_input in = { + .fp = fp, + }; + + return __scanf(&in, fmt, &args); +} diff --git a/src/stdio/vscanf.c b/src/stdio/vscanf.c new file mode 100644 index 0000000..e16da94 --- /dev/null +++ b/src/stdio/vscanf.c @@ -0,0 +1,11 @@ +#include +#include + +int vscanf(char const * restrict fmt, va_list args) +{ + struct __scanf_input in = { + .fp = stdin, + }; + + return __scanf(&in, fmt, &args); +} diff --git a/src/stdio/vsscanf.c b/src/stdio/vsscanf.c new file mode 100644 index 0000000..a71243b --- /dev/null +++ b/src/stdio/vsscanf.c @@ -0,0 +1,12 @@ +#include +#include + +int vsscanf(const char * restrict str, char const * restrict fmt, va_list args) +{ + /* This is valid even if str=NULL. */ + struct __scanf_input in = { + .str = str, + }; + + return __scanf(&in, fmt, &args); +} \ No newline at end of file diff --git a/src/stdlib/strto_fp.c b/src/stdlib/strto_fp.c index 14e089e..b97d44e 100644 --- a/src/stdlib/strto_fp.c +++ b/src/stdlib/strto_fp.c @@ -1,4 +1,4 @@ -#include "stdlib_p.h" +#include #include #include @@ -126,6 +126,8 @@ static bool expect(struct __scanf_input *input, char const *sequence) int __strto_fp(struct __scanf_input *input, double *out, float *outf, long double *outl) { + input->currentlength = 0; + /* Skip initial whitespace */ while(isspace(__scanf_peek(input))) __scanf_in(input); diff --git a/src/stdlib/strto_int.c b/src/stdlib/strto_int.c index 6bbb20d..d123153 100644 --- a/src/stdlib/strto_int.c +++ b/src/stdlib/strto_int.c @@ -1,12 +1,16 @@ -#include "stdlib_p.h" +#include #include #include #include #include +#include int __strto_int(struct __scanf_input *input, int base, long *outl, long long *outll, bool use_unsigned) { + input->currentlength = 0; + + /* Skip initial whitespace */ while(isspace(__scanf_peek(input))) __scanf_in(input); diff --git a/src/stdlib/strtod.c b/src/stdlib/strtod.c index 130233b..76fc462 100644 --- a/src/stdlib/strtod.c +++ b/src/stdlib/strtod.c @@ -1,4 +1,4 @@ -#include "stdlib_p.h" +#include #include double strtod(char const * restrict ptr, char ** restrict endptr) diff --git a/src/stdlib/strtof.c b/src/stdlib/strtof.c index 38240ea..481cbc8 100644 --- a/src/stdlib/strtof.c +++ b/src/stdlib/strtof.c @@ -1,4 +1,4 @@ -#include "stdlib_p.h" +#include #include float strtof(char const * restrict ptr, char ** restrict endptr) diff --git a/src/stdlib/strtol.c b/src/stdlib/strtol.c index c0609b3..81a263e 100644 --- a/src/stdlib/strtol.c +++ b/src/stdlib/strtol.c @@ -1,4 +1,4 @@ -#include "stdlib_p.h" +#include #include long int strtol(char const * restrict ptr, char ** restrict endptr, int base) diff --git a/src/stdlib/strtold.c b/src/stdlib/strtold.c index bf6421b..3f9f6b9 100644 --- a/src/stdlib/strtold.c +++ b/src/stdlib/strtold.c @@ -1,4 +1,4 @@ -#include "stdlib_p.h" +#include #include long double strtold(char const * restrict ptr, char ** restrict endptr) diff --git a/src/stdlib/strtoll.c b/src/stdlib/strtoll.c index 2defd3d..12098dc 100644 --- a/src/stdlib/strtoll.c +++ b/src/stdlib/strtoll.c @@ -1,4 +1,4 @@ -#include "stdlib_p.h" +#include #include long long int strtoll(char const * restrict ptr, char ** restrict endptr, diff --git a/src/stdlib/strtoul.c b/src/stdlib/strtoul.c index a92c265..d8e9386 100644 --- a/src/stdlib/strtoul.c +++ b/src/stdlib/strtoul.c @@ -1,4 +1,4 @@ -#include "stdlib_p.h" +#include #include unsigned long int strtoul(char const * restrict ptr, char ** restrict endptr, diff --git a/src/stdlib/strtoull.c b/src/stdlib/strtoull.c index aad4bd3..1a05f96 100644 --- a/src/stdlib/strtoull.c +++ b/src/stdlib/strtoull.c @@ -1,4 +1,4 @@ -#include "stdlib_p.h" +#include #include unsigned long long int strtoull(char const * restrict ptr,